summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-12-21 13:47:53 +0000
committerMartin Odersky <odersky@gmail.com>2005-12-21 13:47:53 +0000
commit99b6474dabc8a4bcc9282f041d48fb9671c4f2b8 (patch)
treec701a1fac4866e0c7c0d41e49edd69c0c633f06f /src/compiler
parent7ccea812b72c15670fb3c5026acb7856a36e7fad (diff)
downloadscala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.gz
scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.bz2
scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.zip
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala15
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
10 files changed, 108 insertions, 48 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index dedfc6b03a..910b6d0f2a 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -113,12 +113,23 @@ abstract class TreeInfo {
case _ => false
}
- /** The longest statement suffix that starts with a constructor */
+ /** The first constructor definitions in `stats' */
def firstConstructor(stats: List[Tree]): Tree = stats.head match {
case constr @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => constr
case _ => firstConstructor(stats.tail)
}
-
+/*
+ /** The super call that calls mixin `mix' in stats */
+ def superCall(stats: List[Tree], mix: Name): Tree = stats match {
+ case scall @ Apply(Select(Super(_, mix1), name), List()) :: _
+ if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && mix1 == mix) =>
+ scall
+ case _ :: stats1 =>
+ superCall(stats1, name)
+ case _ =>
+ assert(false, "no supercall to " + mix + " in " + stats);
+ }
+*/
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name): boolean =
operator.length > 0 && operator(operator.length - 1) != ':';
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 0634ace4d0..36f6d5890e 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1552,8 +1552,11 @@ import Tokens._;
/** ClassTemplate ::= [`extends' TemplateParents] [[NL] TemplateBody]
* TemplateParents ::= SimpleType {`(' [Exprs] `)'} {`with' SimpleType}
*/
- def classTemplate(mods: Modifiers, name: Name, vparamss: List[List[ValDef]]): Template = {
- val ret = atPos(in.currentPos) {
+ def classTemplate(mods: Modifiers, name: Name, vparamss: List[List[ValDef]]): Template =
+ atPos(in.currentPos) {
+ def acceptEmptyTemplateBody(msg: String): unit =
+ if (!(in.token == SEMI || in.token == NEWLINE || in.token == COMMA || in.token == RBRACE))
+ syntaxError(msg, true);
val parents = new ListBuffer[Tree];
val argss = new ListBuffer[List[Tree]];
if (in.token == EXTENDS) {
@@ -1568,25 +1571,21 @@ import Tokens._;
in.nextToken();
parents += simpleType()
}
- } else argss += List();
+ } else {
+ if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected");
+ argss += List()
+ }
if (name != nme.ScalaObject.toTypeName)
parents += scalaScalaObjectConstr;
if (mods.hasFlag(Flags.CASE)) parents += caseClassConstr;
val ps = parents.toList;
if (in.token == NEWLINE && in.next.token == LBRACE) in.nextToken();
var body =
- if (in.token == LBRACE) {
- templateBody()
- } else {
- if (!(in.token == SEMI || in.token == NEWLINE || in.token == COMMA || in.token == RBRACE))
- syntaxError("`extends' or `{' expected", true);
- List()
- }
+ if (in.token == LBRACE) templateBody()
+ else { acceptEmptyTemplateBody("`{' expected"); List() }
if (!mods.hasFlag(Flags.TRAIT)) Template(ps, vparamss, argss.toList, body)
else Template(ps, body)
}
- ret;
- }
////////// TEMPLATES ////////////////////////////////////////////////////////////
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 6903f2b504..b4f760220f 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -188,13 +188,13 @@ import Flags._;
var i = 0;
var j = fullname.pos('.', i);
while (j < fullname.length) {
- sym = sym.info.nonPrivateMember(fullname.subName(i, j));
+ sym = sym.info.member(fullname.subName(i, j));
i = j + 1;
j = fullname.pos('.', i)
}
val result =
- if (module) sym.info.nonPrivateMember(fullname.subName(i, j)).suchThat(.hasFlag(MODULE));
- else sym.info.nonPrivateMember(fullname.subName(i, j).toTypeName);
+ if (module) sym.info.member(fullname.subName(i, j)).suchThat(.hasFlag(MODULE));
+ else sym.info.member(fullname.subName(i, j).toTypeName);
if (result == NoSymbol)
throw new FatalError((if (module) "object " else "class ") + fullname + " not found.");
result
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 4eaac75fcf..58ef0187e1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1607,6 +1607,8 @@ import Flags._;
case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
(tparams1.length == tparams2.length &&
(res1 matches res2.substSym(tparams2, tparams1)))
+ case Pair(PolyType(List(), rtp1), MethodType(List(), rtp2)) => matchesType(rtp1, rtp2)
+ case Pair(MethodType(List(), rtp1), PolyType(List(), rtp2)) => matchesType(rtp1, rtp2)
case Pair(PolyType(List(), rtp1), _) => matchesType(rtp1, tp2)
case Pair(_, PolyType(List(), rtp2)) => matchesType(tp1, rtp2)
case Pair(MethodType(_, _), _) => false
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 0e56cf8824..6b633f389f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -289,7 +289,7 @@ abstract class ClassfileParser {
def parseMethod(): unit = {
val jflags = in.nextChar();
var sflags = transFlags(jflags);
- if ((sflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE;
+ if ((jflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE;
if ((sflags & PRIVATE) != 0) {
in.skip(4); skipAttributes();
} else {
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 95a500634b..466ed4674c 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -211,7 +211,8 @@ abstract class ExplicitOuter extends InfoTransform {
// as constructor arguments might be missing
}
val mixinConstructorCalls =
- for (val mixin <- clazz.info.parents.tail; !(mixin.symbol hasFlag INTERFACE)) yield
+ for (val mixin <- clazz.info.parents.tail;
+ !(mixin.symbol hasFlag INTERFACE) && mixin.symbol != ScalaObjectClass) yield
mixinConstructorCall(mixin.symbol);
tree match {
case Block(supercall :: stats, expr) =>
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 08935e7e16..bcdd9b09b8 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -282,7 +282,7 @@ abstract class Mixin extends InfoTransform {
true
}
if (newDefs.isEmpty) stats
- else stats.filter(isNotDuplicate) ::: newDefs
+ else newDefs ::: stats.filter(isNotDuplicate)//!!!
}
def completeSuperAccessor(stat: Tree) = stat match {
case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index e982ac1ba1..d80f573029 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -13,6 +13,7 @@ import symtab.Flags._;
import definitions._;
import posAssigner.atPos;
+ // statistics
var normM = 0;
var normP = 0;
var normO = 0;
@@ -152,17 +153,24 @@ import symtab.Flags._;
tp1
}
+ private val stdErrorClass = RootClass.newErrorClass(nme.ERROR.toTypeName);
+ private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR);
+
/** The context-dependent inferencer part */
class Inferencer(context: Context) {
/* -- Error Messages ----------------------------------------------------- */
def setError[T <: Tree](tree: T): T = {
- val name = newTermName("<error: " + tree + ">");
if (tree.hasSymbol)
- tree.setSymbol(
- if (tree.isType) context.owner.newErrorClass(name.toTypeName)
- else context.owner.newErrorValue(name));
+ if (context.reportGeneralErrors) {
+ val name = newTermName("<error: " + tree.symbol + ">");
+ tree.setSymbol(
+ if (tree.isType) context.owner.newErrorClass(name.toTypeName)
+ else context.owner.newErrorValue(name));
+ } else {
+ tree.setSymbol(if (tree.isType) stdErrorClass else stdErrorValue)
+ }
tree.setType(ErrorType)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index f60ffae9b5..f6552d9fc5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -96,7 +96,10 @@ abstract class RefChecks extends InfoTransform {
* 1.7. If O is an abstract type then
* either M is an abstract type, and M's bounds are sharper than O's bounds.
* or M is an unparameterized type alias or class which conforms to O's bounds.
- * 1.8. If O and M are values, then M's type is a subtype of O's type.
+ * 1.8. If O and M are values, then
+ * 1.8.1 M's type is a subtype of O's type, or
+ * 1.8.2 M is of type []S, O is of type ()T and S <: T, or
+ * 1.8.3 M is of type ()S, O is of type []T and S <: T, or
* 2. Check that only abstract classes have deferred members
* 3. Check that every member with an `override' modifier
* overrides some other member.
@@ -115,6 +118,12 @@ abstract class RefChecks extends InfoTransform {
else "")))
);
+ def overridesType(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
+ case Pair(MethodType(List(), rtp1), PolyType(List(), rtp2)) => rtp1 <:< rtp2
+ case Pair(PolyType(List(), rtp1), MethodType(List(), rtp2)) => rtp1 <:< rtp2
+ case _ => tp1 <:< tp2
+ }
+
/* Check that all conditions for overriding `other' by `member' are met. */
def checkOverride(clazz: Symbol, member: Symbol, other: Symbol): unit = {
val pos = if (member.owner == clazz) member.pos else clazz.pos;
@@ -179,8 +188,9 @@ abstract class RefChecks extends InfoTransform {
if (!(self.memberInfo(other).bounds containsType self.memberType(member))) // (1.7)
overrideTypeError();
} else if (other.isTerm) {
- if (!(self.memberInfo(member) <:< (self.memberInfo(other)))) // 8
+ if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8
overrideTypeError();
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e6d2e0e8a3..3664e641bb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -279,8 +279,11 @@ import scala.collection.mutable.{HashMap, ListBuffer}
* unless followed by explicit type application.
* (4) Do the following to unapplied methods used as values:
* (4.1) If the method has only implicit parameters pass implicit arguments
- * (4.2) otherwise, convert to function by eta-expansion,
- * except if the method is a constructor, in which case we issue an error.
+ * (4.2) otherwise, if `pt' is a function type and method is not a constructor,
+ * convert to function by eta-expansion,
+ * (4.3) otherwise, if the method is nullary with a result type compatible to `pt'
+ * and it is not a constructor, apply it to ()
+ * otherwise issue an error
* (5) Convert a class type that serves as a constructor in a pattern as follows:
* (5.1) If this type refers to a case class, set tree's type to the unique
* instance of its primary constructor that is a subtype of the expected type.
@@ -326,15 +329,21 @@ import scala.collection.mutable.{HashMap, ListBuffer}
adapt(tree, mode, pt)
} else tree;
typed(applyImplicitArgs(tree1), mode, pt)
- case mt: MethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- isCompatible(tree.tpe, pt)) => // (4.2)
- if (tree.symbol.isConstructor || pt == WildcardType ||
- !(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) {
- errorTree(tree, "missing arguments for " + tree.symbol) //debug
- } else {
- if (settings.debug.value) log("eta-expanding " + tree + ":" + tree.tpe + " to " + pt);//debug
+ case mt: MethodType
+ if (((mode & (EXPRmode | FUNmode)) == EXPRmode) &&
+ (context.undetparams.isEmpty || (mode & POLYmode) != 0)) =>
+ if (!tree.symbol.isConstructor && pt != WildcardType && isCompatible(mt, pt) &&
+ (pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) { // (4.2)
+ if (settings.debug.value) log("eta-expanding " + tree + ":" + tree.tpe + " to " + pt);
typed(etaExpand(tree), mode, pt)
- }
+ } else if (!tree.symbol.isConstructor &&
+ mt.paramTypes.isEmpty && isCompatible(mt.resultType, pt)) { // (4.3)
+ typed(Apply(tree, List()) setPos tree.pos)
+ } else {
+ if (context.reportGeneralErrors)
+ error(tree.pos, "missing arguments for " + tree.symbol);
+ setError(tree)
+ }
case _ =>
if (tree.isType) {
val clazz = tree.tpe.symbol;
@@ -409,7 +418,7 @@ import scala.collection.mutable.{HashMap, ListBuffer}
}
}
if (settings.debug.value) log("error tree = " + tree);
- typeErrorTree(tree, tree.tpe, pt)
+ typeErrorTree(tree, tree.tpe, pt)
}
}
}
@@ -426,16 +435,35 @@ import scala.collection.mutable.{HashMap, ListBuffer}
else qual
} else qual;
- private def completeSuperType(supertpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
+ private def completeParentType(tpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
enclTparams foreach context.scope.enter;
namer.enterValueParams(context.owner, vparamss);
- val newTree = New(supertpt)
- .setType(PolyType(tparams, appliedType(supertpt.tpe, tparams map (.tpe))));
- val tree = typed(atPos(supertpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
+ val newTree = New(tpt)
+ .setType(PolyType(tparams, appliedType(tpt.tpe, tparams map (.tpe))));
+ val tree = typed(atPos(tpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
if (settings.debug.value) log("superconstr " + tree + " co = " + context.owner);//debug
tree.tpe
}
+/*
+ def completeParentType(tpt: Tree, templ: Template): Tree =
+ if (tpt.hasSymbol) {
+ val tparams = tpt.symbol.typeParams;
+ if (!tparams.isEmpty) {
+ val constr @ DefDef(_, _, _, vparamss, _, rhs) = treeInfo.firstConstructor(templ.body);
+ val Apply(_, superargs) = treeInfo.superCall(rhs, tpt.symbol.name);
+ val outercontext = context.outer;
+ TypeTree(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .completeParentType(
+ tpt,
+ tparams,
+ context.owner.unsafeTypeParams,
+ vparamss map (.map(.duplicate.asInstanceOf[ValDef])),
+ superargs map (.duplicate))) setPos tpt.pos;
+ } else tpt
+ } else tpt
+*/
def parentTypes(templ: Template): List[Tree] = try {
if (templ.parents.isEmpty) List()
else {
@@ -453,8 +481,8 @@ import scala.collection.mutable.{HashMap, ListBuffer}
treeInfo.firstConstructor(templ.body);
val outercontext = context.outer;
supertpt = TypeTree(
- newTyper(outercontext.makeNewScope(constr, outercontext.owner/*.newValue(templ.pos, newTermName("<dummy>"))*/))
- .completeSuperType(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .completeParentType(
supertpt,
tparams,
context.owner.unsafeTypeParams,
@@ -1467,9 +1495,10 @@ import scala.collection.mutable.{HashMap, ListBuffer}
private def typedImplicit(pos: int, info: ImplicitInfo, pt: Type, local: boolean): Tree =
if (isCompatible(depoly(info.tpe), pt)) {
var tree: Tree = EmptyTree;
- def fail(reason: String): Tree = {
+ def fail(reason: String, sym1: Symbol, sym2: Symbol): Tree = {
if (settings.debug.value)
- log(tree.toString() + " is not a valid implicit value because:\n" + reason);
+ log(tree.toString() + " is not a valid implicit value because:\n" + reason +
+ sym1 + " " + sym2);
EmptyTree
}
try {
@@ -1481,10 +1510,10 @@ import scala.collection.mutable.{HashMap, ListBuffer}
val tree1 = adapt(tree, EXPRmode, pt);
if (settings.debug.value)
log("adapted implicit " + tree.symbol + ":" + tree1.tpe + " to " + pt);//debug
- if (info.sym == tree.symbol) tree1
- else fail("syms differ: " + tree.symbol + " " + info.sym)
+ if (tree1.tpe != ErrorType && info.sym == tree.symbol) tree1
+ else fail("syms differ: ", tree.symbol, info.sym)
} catch {
- case ex: TypeError => fail(ex.getMessage())
+ case ex: TypeError => fail(ex.getMessage(), NoSymbol, NoSymbol)
}
} else EmptyTree;