diff options
author | Martin Odersky <odersky@gmail.com> | 2005-12-21 13:47:53 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-12-21 13:47:53 +0000 |
commit | 99b6474dabc8a4bcc9282f041d48fb9671c4f2b8 (patch) | |
tree | c701a1fac4866e0c7c0d41e49edd69c0c633f06f /src/compiler | |
parent | 7ccea812b72c15670fb3c5026acb7856a36e7fad (diff) | |
download | scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.gz scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.bz2 scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.zip |
Diffstat (limited to 'src/compiler')
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; |