diff options
author | Martin Odersky <odersky@gmail.com> | 2006-04-11 16:22:28 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2006-04-11 16:22:28 +0000 |
commit | e3fc3506c7c918aba5cc7c3baabca95de8f6ac4c (patch) | |
tree | 67c1ec643f9b418914e0f82341785cd7860d77d1 /src | |
parent | a0c48ce649c3d320623a3369b8ade2665b71f613 (diff) | |
download | scala-e3fc3506c7c918aba5cc7c3baabca95de8f6ac4c.tar.gz scala-e3fc3506c7c918aba5cc7c3baabca95de8f6ac4c.tar.bz2 scala-e3fc3506c7c918aba5cc7c3baabca95de8f6ac4c.zip |
1. Allowed local implicits
2. Small change in syntax to make postfix operators more robust 3.
Suppresses duplicate and redundant error messages 4. Improve `bad
signature' diagnostics
Diffstat (limited to 'src')
13 files changed, 393 insertions, 343 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index d22e3abfa5..a593538852 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -27,7 +27,14 @@ trait CompilationUnits requires Global { def position(pos: int) = new Position(source, pos); - def error(pos: int, msg: String) = reporter.error(position(pos), msg); + val errorPositions = new HashSet[int] + + def error(pos: int, msg: String) = { + if (!(errorPositions contains pos)) { + errorPositions += pos; + reporter.error(position(pos), msg); + } + } def warning(pos: int, msg: String) = reporter.warning(position(pos), msg); override def toString() = source.toString(); diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 763e53d606..77656ea50d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -66,6 +66,8 @@ trait Trees requires Global { def isType = false; def isEmpty = false; + def isErroneous = tpe != null && tpe.isErroneous; + override def toString(): String = { val buffer = new StringWriter(); val printer = treePrinters.create(new PrintWriter(buffer)); diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 1d73da9005..35bb620932 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -151,7 +151,7 @@ trait Parsers requires SyntaxAnalyzer { } def isLocalModifier: boolean = in.token match { - case ABSTRACT | FINAL | SEALED => true + case ABSTRACT | FINAL | SEALED | IMPLICIT => true case _ => false } @@ -166,7 +166,7 @@ trait Parsers requires SyntaxAnalyzer { case _ => false } - def isExprIntro: boolean = in.token match { + def isExprIntroToken(token: int): boolean = token match { case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER | THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE | @@ -174,6 +174,8 @@ trait Parsers requires SyntaxAnalyzer { case _ => false } + def isExprIntro: boolean = isExprIntroToken(in.token) + /////// COMMENT AND ATTRIBUTE COLLECTION ////////////////////////////////////// /** Join the comment associated with a definition @@ -467,8 +469,15 @@ trait Parsers requires SyntaxAnalyzer { in.nextToken(); } - def newLineOptWhenFollowedBy(token: int): unit = - if (in.token == NEWLINE && in.next.token == token) newLineOpt(); + def newLineOptWhenFollowedBy(token: int): unit = { + // note: next is defined here because current == NEWLINE + if (in.token == NEWLINE && in.next.token == token) newLineOpt() + } + + def newLineOptWhenFollowing(p: int => boolean): unit = { + // note: next is defined here because current == NEWLINE + if (in.token == NEWLINE && p(in.next.token)) newLineOpt() + } //////// TYPES /////////////////////////////////////////////////////////////// @@ -755,7 +764,7 @@ trait Parsers requires SyntaxAnalyzer { true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name)); opstack = OpInfo(top, in.name, in.currentPos) :: opstack; ident(); - newLineOpt(); + newLineOptWhenFollowing(isExprIntroToken); if (isExprIntro) { top = prefixExpr(); } else { @@ -1116,9 +1125,9 @@ trait Parsers requires SyntaxAnalyzer { ////////// MODIFIERS //////////////////////////////////////////////////////////// /** Modifiers ::= {Modifier} - * Modifier ::= LocalClassModifier + * Modifier ::= LocalModifier * | private [ "[" Id "]" ] - * | protected | override | implicit + * | protected | override */ def modifiers(): Modifiers = { var privateWithin: Name = nme.EMPTY.toTypeName; @@ -1153,10 +1162,10 @@ trait Parsers requires SyntaxAnalyzer { Modifiers(mods, privateWithin) } - /** LocalClassModifiers ::= {LocalClassModifier} - * LocalClassModifier ::= abstract | mixin | final | sealed + /** LocalModifiers ::= {LocalModifier} + * LocalModifier ::= abstract | final | sealed | implicit */ - def localClassModifiers(): Modifiers = { + def localModifiers(): Modifiers = { def loop(mods: int): int = in.token match { case ABSTRACT => loop(addMod(mods, Flags.ABSTRACT)) @@ -1164,6 +1173,8 @@ trait Parsers requires SyntaxAnalyzer { loop(addMod(mods, Flags.FINAL)) case SEALED => loop(addMod(mods, Flags.SEALED)) + case IMPLICIT => + loop(addMod(mods, Flags.IMPLICIT)) case _ => mods } @@ -1828,12 +1839,22 @@ trait Parsers requires SyntaxAnalyzer { /** BlockStatSeq ::= { BlockStat StatementSeparator } [ResultExpr] * BlockStat ::= Import - * | Def + * | [implicit] Def * | LocalModifiers TmplDef * | Expr1 * | */ def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] = { + def localDef(mods: Modifiers) = { + if (!(mods hasFlag ~Flags.IMPLICIT)) stats ++= defOrDcl(mods) + else stats += tmplDef(mods) + if (in.token == RBRACE || in.token == CASE) + syntaxError("block must end in result expression, not in definition", false) + else + acceptStatSep() + if (in.token == RBRACE || in.token == CASE) + stats += Literal(()).setPos(in.currentPos) + } while ((in.token != RBRACE) && (in.token != EOF) && (in.token != CASE)) { if (in.token == IMPORT) { stats ++= importClause(); @@ -1842,20 +1863,9 @@ trait Parsers requires SyntaxAnalyzer { stats += expr(false, true); if (in.token != RBRACE && in.token != CASE) acceptStatSep(); } else if (isDefIntro) { - stats ++= defOrDcl(NoMods); - if (in.token == RBRACE || in.token == CASE) - syntaxError("block must end in result expression, not in definition", false) - else - acceptStatSep(); - if (in.token == RBRACE || in.token == CASE) { - stats += Literal(()).setPos(in.currentPos) - } + localDef(NoMods) } else if (isLocalModifier) { - stats += tmplDef(localClassModifiers()); - acceptStatSep(); - if (in.token == RBRACE || in.token == CASE) { - stats += Literal(()).setPos(in.currentPos) - } + localDef(localModifiers()) } else if (in.token == SEMI || in.token == NEWLINE) { in.nextToken(); } else { diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 112294ead3..e21ac25ff1 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -174,6 +174,7 @@ trait Symbols requires SymbolTable { final def isThisSym = isTerm && name == nme.this_; final def isThisSkolem = isTerm && deSkolemize != this; final def isError = hasFlag(IS_ERROR); + final def isErroneous = isError || isInitialized && tpe.isErroneous final def isTrait = isClass & hasFlag(TRAIT); final def isAliasType = isType && !isClass && !hasFlag(DEFERRED); final def isAbstractType = isType && !isClass && hasFlag(DEFERRED); diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 5ec350c35f..428bdb3ab6 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -122,6 +122,13 @@ trait Types requires SymbolTable { /** Is this type produced as a repair for an error? */ def isError: boolean = symbol.isError; + /** Is this type produced as a repair for an error? */ + def isErroneous: boolean = { + ErroneousTraverser.result = false; + ErroneousTraverser.traverse(this); + ErroneousTraverser.result + } + /** Does this type denote a stable reference (i.e. singleton type)? */ def isStable: boolean = false; @@ -1340,6 +1347,18 @@ trait Types requires SymbolTable { } } + /** A map to implement the contains method */ + object ErroneousTraverser extends TypeTraverser { + var result: boolean = _; + def traverse(tp: Type): TypeTraverser = { + if (!result) { + result = tp.isError + mapOver(tp) + } + this + } + } + /** A map to compute the most deeply nested owner that contains all the symbols * of thistype or prefixless typerefs/singletype occurrences in given type */ object commonOwnerMap extends TypeMap { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 0d72ae43b9..8e8cadd21d 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -487,7 +487,7 @@ abstract class ClassfileParser { case nme.InnerClassesATTR => parseInnerClasses() case nme.ScalaSignatureATTR => - unpickler.unpickle(in.buf, in.bp, clazz, staticModule); + unpickler.unpickle(in.buf, in.bp, clazz, staticModule, in.file.toString()); this.isScala = true; case nme.JacoMetaATTR => val meta = pool.getName(in.nextChar).toString().trim(); diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala index cb7e401b1c..587940e6b8 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala @@ -24,8 +24,8 @@ abstract class SymblfileParser { assert(current == null, current); current = file; val in = new AbstractFileReader(file); - if (root.isModule) unpickler.unpickle(in.buf, 0, root.linkedClass, root) - else unpickler.unpickle(in.buf, 0, root, root.linkedModule); + if (root.isModule) unpickler.unpickle(in.buf, 0, root.linkedClass, root, file.toString()) + else unpickler.unpickle(in.buf, 0, root, root.linkedModule, file.toString()); current = null } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala index 7db3154d77..fea767d9dc 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -18,14 +18,14 @@ abstract class UnPickler { val global: Global; import global._; - def unpickle(bytes: Array[byte], offset: int, classRoot: Symbol, moduleRoot: Symbol): unit = try { + def unpickle(bytes: Array[byte], offset: int, classRoot: Symbol, moduleRoot: Symbol, filename: String): unit = try { new UnPickle(bytes, offset, classRoot, moduleRoot); } catch { case ex: IOException => throw ex case ex: Throwable => if (settings.debug.value) ex.printStackTrace(); - throw new RuntimeException("error reading Scala signature of " + classRoot.nameString + ": " + ex.getMessage()); + throw new RuntimeException("error reading Scala signature of "+filename+": "+ex.getMessage()) } private class UnPickle(bytes: Array[byte], offset: int, classRoot: Symbol, moduleRoot: Symbol) extends PickleBuffer(bytes, offset, -1) { diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index c76493b9ea..6513c085bd 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -307,11 +307,7 @@ abstract class LambdaLift extends InfoTransform { case Return(Block(stats, value)) => Block(stats, copy.Return(tree, value)) setType tree.tpe setPos tree.pos case Return(expr) => - if (sym != currentOwner.enclMethod) { - System.out.println(sym);//debug - System.out.println(currentOwner.enclMethod);//debug - unit.error(tree.pos, "non-local return not yet implemented"); - } + assert(sym == currentOwner.enclMethod, sym) tree case Apply(fn, args) => copy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args)); diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 128ef3c7d3..cd1a9959dd 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -7,6 +7,7 @@ package scala.tools.nsc.transform; import symtab.Flags._; import scala.collection.mutable.HashMap +import scala.tools.nsc.util.HashSet /*<export>*/ /** - uncurry all symbol and tree types (@see UnCurryPhase) @@ -219,7 +220,9 @@ abstract class UnCurry extends InfoTransform { case Match(_, cases) => val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam)); def transformCase(cdef: CaseDef): CaseDef = - resetAttrs(CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true))); + substParam( + resetAttrs( + CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true)))) if (cases exists treeInfo.isDefaultCase) Literal(true) else Match( @@ -448,11 +451,19 @@ abstract class UnCurry extends InfoTransform { } private val resetAttrs = new Traverser { + val erasedSyms = new HashSet[Symbol](8) override def traverse(tree: Tree): unit = tree match { case EmptyTree | TypeTree() => ; + case Bind(_, body) => + if (tree.hasSymbol && tree.symbol != NoSymbol) { + erasedSyms.addEntry(tree.symbol); + tree.symbol = NoSymbol; + } + tree.tpe = null; + super.traverse(tree) case _ => - if (tree.hasSymbol) tree.symbol = NoSymbol; + if (tree.hasSymbol && erasedSyms.contains(tree.symbol)) tree.symbol = NoSymbol; tree.tpe = null; super.traverse(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f24d2a21a4..ef1b48aeef 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -183,8 +183,10 @@ trait Contexts requires Analyzer { "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) + "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) + "\nmatch " + rest); - if (reportAmbiguousErrors) unit.error(pos, msg) - else throw new TypeError(msg); + if (reportAmbiguousErrors) { + if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous) + unit.error(pos, msg) + } else throw new TypeError(msg); } def outerContext(clazz: Symbol): Context = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 22143b8b78..a2c1da2bd4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -61,7 +61,7 @@ trait Infer requires Analyzer { assert(constr.inst != null);//debug if (constr.inst != NoType) instantiate(constr.inst) else throw new DeferredNoInstance(() => - "no unique instantiation of type variable " + origin + " could be found"); + "no unique instantiation of type variable " + origin + " could be found"); case _ => instantiateMap.mapOver(tp) } @@ -88,46 +88,46 @@ trait Infer requires Analyzer { * @throws NoInstance */ private def solve(tvars: List[TypeVar], tparams: List[Symbol], variances: List[int], - upper: boolean): List[Type] = { + upper: boolean): List[Type] = { val config = tvars zip (tparams zip variances); def solveOne(tvar: TypeVar, tparam: Symbol, variance: int): unit = { if (tvar.constr.inst == NoType) { - val up = if (variance != CONTRAVARIANT) upper else !upper; - tvar.constr.inst = null; - val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo; - var cyclic = false; - for (val Pair(tvar2, Pair(tparam2, variance2)) <- config) { - if (tparam2 != tparam && + val up = if (variance != CONTRAVARIANT) upper else !upper; + tvar.constr.inst = null; + val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo; + var cyclic = false; + for (val Pair(tvar2, Pair(tparam2, variance2)) <- config) { + if (tparam2 != tparam && ((bound contains tparam2) || - up && (tparam2.info.bounds.lo =:= tparam.tpe) || - !up && (tparam2.info.bounds.hi =:= tparam.tpe))) { - if (tvar2.constr.inst == null) cyclic = true; - solveOne(tvar2, tparam2, variance2); + up && (tparam2.info.bounds.lo =:= tparam.tpe) || + !up && (tparam2.info.bounds.hi =:= tparam.tpe))) { + if (tvar2.constr.inst == null) cyclic = true; + solveOne(tvar2, tparam2, variance2); } - } - if (!cyclic) { - if (up) { - if (bound.symbol != AnyClass) { - tvar.constr.hibounds = - bound.subst(tparams, tvars) :: tvar.constr.hibounds; - } - for (val tparam2 <- tparams) - if (tparam2.info.bounds.lo =:= tparam.tpe) - tvar.constr.hibounds = - tparam2.tpe.subst(tparams, tvars) :: tvar.constr.hibounds; - } else { - if (bound.symbol != AllClass && bound.symbol != tparam) { - tvar.constr.lobounds = - bound.subst(tparams, tvars) :: tvar.constr.lobounds; - } - for (val tparam2 <- tparams) - if (tparam2.info.bounds.hi =:= tparam.tpe) - tvar.constr.lobounds = - tparam2.tpe.subst(tparams, tvars) :: tvar.constr.lobounds; - } - } - tvar.constr.inst = if (up) glb(tvar.constr.hibounds) else lub(tvar.constr.lobounds) + } + if (!cyclic) { + if (up) { + if (bound.symbol != AnyClass) { + tvar.constr.hibounds = + bound.subst(tparams, tvars) :: tvar.constr.hibounds; + } + for (val tparam2 <- tparams) + if (tparam2.info.bounds.lo =:= tparam.tpe) + tvar.constr.hibounds = + tparam2.tpe.subst(tparams, tvars) :: tvar.constr.hibounds; + } else { + if (bound.symbol != AllClass && bound.symbol != tparam) { + tvar.constr.lobounds = + bound.subst(tparams, tvars) :: tvar.constr.lobounds; + } + for (val tparam2 <- tparams) + if (tparam2.info.bounds.hi =:= tparam.tpe) + tvar.constr.lobounds = + tparam2.tpe.subst(tparams, tvars) :: tvar.constr.lobounds; + } + } + tvar.constr.inst = if (up) glb(tvar.constr.hibounds) else lub(tvar.constr.lobounds) } } for (val Pair(tvar, Pair(tparam, variance)) <- config) solveOne(tvar, tparam, variance); @@ -165,9 +165,9 @@ trait Infer requires Analyzer { if (tree.hasSymbol) if (context.reportGeneralErrors) { val name = newTermName("<error: " + tree.symbol + ">"); - tree.setSymbol( - if (tree.isType) context.owner.newErrorClass(name.toTypeName) - else context.owner.newErrorValue(name)); + tree.setSymbol( + if (tree.isType) context.owner.newErrorClass(name.toTypeName) + else context.owner.newErrorValue(name)); } else { tree.setSymbol(if (tree.isType) stdErrorClass else stdErrorValue) } @@ -179,11 +179,11 @@ trait Infer requires Analyzer { def treeSymTypeMsg(tree: Tree): String = if (tree.symbol == null) - "expression of type " + tree.tpe + "expression of type " + tree.tpe else if (tree.symbol.hasFlag(OVERLOADED)) - "overloaded method " + tree.symbol + " with alternatives " + tree.tpe + "overloaded method " + tree.symbol + " with alternatives " + tree.tpe else ( - tree.symbol.toString() + + tree.symbol.toString() + (if (tree.tpe.paramSectionCount > 0) ": " else " of type ") + tree.tpe ); @@ -200,19 +200,19 @@ trait Infer requires Analyzer { context.error(pos, msg); def errorTree(tree: Tree, msg: String): Tree = { - error(tree.pos, msg); + if (!tree.isErroneous) error(tree.pos, msg); setError(tree) } def typeError(pos: int, found: Type, req: Type): unit = - if (!found.isError && !req.isError) { - error(pos, + if (!found.isErroneous && !req.isErroneous) { + error(pos, "type mismatch" + foundReqMsg(found, req) + - (if (!(found.resultType eq found) && isWeaklyCompatible(found.resultType, req)) - "\n possible cause: missing arguments for method or constructor" - else "")); - if (settings.explaintypes.value) - explainTypes(found, req); + (if (!(found.resultType eq found) && isWeaklyCompatible(found.resultType, req)) + "\n possible cause: missing arguments for method or constructor" + else "")); + if (settings.explaintypes.value) + explainTypes(found, req); } def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = { @@ -226,32 +226,32 @@ trait Infer requires Analyzer { * in current context. */ def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree = if (sym.isError) { - tree setSymbol sym setType ErrorType + tree setSymbol sym setType ErrorType } else { sym.toplevelClass match { - case clazz : ClassSymbol => - // System.err.println("TOP: " + clazz + " " + clazz.sourceFile); - if (clazz.sourceFile != null) - global.currentRun.currentUnit.depends += clazz.sourceFile; - - case _ => - } - val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super])); - if (sym1 == NoSymbol) { - if (settings.debug.value) { - System.out.println(context); + case clazz : ClassSymbol => + // System.err.println("TOP: " + clazz + " " + clazz.sourceFile); + if (clazz.sourceFile != null) + global.currentRun.currentUnit.depends += clazz.sourceFile; + + case _ => + } + val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super])); + if (sym1 == NoSymbol) { + if (settings.debug.value) { + System.out.println(context); System.out.println(tree); System.out.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType)); - } - errorTree(tree, sym.toString() + " cannot be accessed in " + - (if (sym.isClassConstructor) context.enclClass.owner else pre.widen)) - } else { + } + errorTree(tree, sym.toString() + " cannot be accessed in " + + (if (sym.isClassConstructor) context.enclClass.owner else pre.widen)) + } else { //System.out.println("check acc " + sym1 + ":" + sym1.tpe + " from " + pre);//DEBUG var owntype = pre.memberType(sym1); if (pre.isInstanceOf[SuperType]) owntype = owntype.substSuper(pre, site.symbol.thisType); - tree setSymbol sym1 setType owntype - } + tree setSymbol sym1 setType owntype + } } def isCompatible(tp: Type, pt: Type): boolean = { @@ -277,11 +277,11 @@ trait Infer requires Analyzer { private def exprTypeArgs(tparams: List[Symbol], restpe: Type, pt: Type): List[Type] = { val tvars = tparams map freshVar; if (isCompatible(restpe.subst(tparams, tvars), pt)) { - try { - solve(tvars, tparams, tparams map varianceInType(restpe), false); - } catch { - case ex: NoInstance => null - } + try { + solve(tvars, tparams, tparams map varianceInType(restpe), false); + } catch { + case ex: NoInstance => null + } } else null } @@ -294,35 +294,35 @@ trait Infer requires Analyzer { * If instantiation of a type parameter fails, * take WildcardType for the proto-type argument. */ def protoTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type, - pt: Type): List[Type] = { + pt: Type): List[Type] = { /** Map type variable to its instance, or, if `variance' is covariant/contravariant, * to its upper/lower bound */ def instantiateToBound(tvar: TypeVar, variance: int): Type = try { //System.out.println("instantiate "+tvar+tvar.constr+" variance = "+variance);//DEBUG - if (tvar.constr.inst != NoType) { - instantiate(tvar.constr.inst) - } else if ((variance & COVARIANT) != 0 && !tvar.constr.hibounds.isEmpty) { - tvar.constr.inst = glb(tvar.constr.hibounds); - instantiate(tvar.constr.inst) - } else if ((variance & CONTRAVARIANT) != 0 && !tvar.constr.lobounds.isEmpty) { - tvar.constr.inst = lub(tvar.constr.lobounds); - instantiate(tvar.constr.inst) + if (tvar.constr.inst != NoType) { + instantiate(tvar.constr.inst) + } else if ((variance & COVARIANT) != 0 && !tvar.constr.hibounds.isEmpty) { + tvar.constr.inst = glb(tvar.constr.hibounds); + instantiate(tvar.constr.inst) + } else if ((variance & CONTRAVARIANT) != 0 && !tvar.constr.lobounds.isEmpty) { + tvar.constr.inst = lub(tvar.constr.lobounds); + instantiate(tvar.constr.inst) } else if (!tvar.constr.hibounds.isEmpty && !tvar.constr.lobounds.isEmpty && glb(tvar.constr.hibounds) <:< lub(tvar.constr.lobounds)) { - tvar.constr.inst = glb(tvar.constr.hibounds); - instantiate(tvar.constr.inst) - } else { - WildcardType - } + tvar.constr.inst = glb(tvar.constr.hibounds); + instantiate(tvar.constr.inst) + } else { + WildcardType + } } catch { - case ex: NoInstance => WildcardType + case ex: NoInstance => WildcardType } val tvars = tparams map freshVar; if (isCompatible(restpe.subst(tparams, tvars), pt)) - List.map2(tparams, tvars) ((tparam, tvar) => - instantiateToBound(tvar, varianceInTypes(formals)(tparam))) + List.map2(tparams, tvars) ((tparam, tvar) => + instantiateToBound(tvar, varianceInTypes(formals)(tparam))) else - tvars map (tvar => WildcardType) + tvars map (tvar => WildcardType) } /** Return inferred type arguments, given type parameters, formal parameters, @@ -342,39 +342,39 @@ trait Infer requires Analyzer { * parameters). */ private def methTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type, - argtpes: List[Type], pt: Type, - uninstantiated: ListBuffer[Symbol]): List[Type] = { + argtpes: List[Type], pt: Type, + uninstantiated: ListBuffer[Symbol]): List[Type] = { val tvars = tparams map freshVar; if (formals.length != argtpes.length) { - throw new NoInstance("parameter lists differ in length"); + throw new NoInstance("parameter lists differ in length"); } // check first whether type variables can be fully defined from // expected result type. if (!isCompatible(restpe.subst(tparams, tvars), pt)) { - throw new DeferredNoInstance(() => - "result type " + normalize(restpe) + " is incompatible with expected type " + pt) + throw new DeferredNoInstance(() => + "result type " + normalize(restpe) + " is incompatible with expected type " + pt) } for (val tvar <- tvars) - if (!isFullyDefined(tvar)) tvar.constr.inst = NoType; + if (!isFullyDefined(tvar)) tvar.constr.inst = NoType; // Then define remaining type variables from argument types. List.map2(argtpes, formals) {(argtpe, formal) => - if (!isCompatible(argtpe.deconst.subst(tparams, tvars), - formal.subst(tparams, tvars))) { - if (settings.explaintypes.value) - explainTypes(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars)); - throw new DeferredNoInstance(() => - "argument expression's type is not compatible with formal parameter type" + - foundReqMsg(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars))) - } - () + if (!isCompatible(argtpe.deconst.subst(tparams, tvars), + formal.subst(tparams, tvars))) { + if (settings.explaintypes.value) + explainTypes(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars)); + throw new DeferredNoInstance(() => + "argument expression's type is not compatible with formal parameter type" + + foundReqMsg(argtpe.deconst.subst(tparams, tvars), formal.subst(tparams, tvars))) + } + () } val targs = solve(tvars, tparams, tparams map varianceInTypes(formals), false); List.map2(tparams, targs) {(tparam, targ) => - if (targ.symbol == AllClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) { - uninstantiated += tparam; - tparam.tpe - } else targ} + if (targ.symbol == AllClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) { + uninstantiated += tparam; + tparam.tpe + } else targ} } @@ -382,45 +382,45 @@ trait Infer requires Analyzer { * function type `ftpe' is applicable to `argtpes' and its result conform to `pt'? */ def isApplicable(undetparams: List[Symbol], ftpe: Type, argtpes: List[Type], pt: Type): boolean = ftpe match { - case MethodType(formals0, restpe) => - val formals = formalTypes(formals0, argtpes.length); - if (undetparams.isEmpty) { - (formals.length == argtpes.length && - isCompatible(argtpes, formals) && - isWeaklyCompatible(restpe, pt)) - } else { - try { - val uninstantiated = new ListBuffer[Symbol]; - val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated); - val result = ( - exprTypeArgs(uninstantiated.toList, restpe.subst(undetparams, targs), pt) != null && - isWithinBounds(undetparams, targs) + case MethodType(formals0, restpe) => + val formals = formalTypes(formals0, argtpes.length); + if (undetparams.isEmpty) { + (formals.length == argtpes.length && + isCompatible(argtpes, formals) && + isWeaklyCompatible(restpe, pt)) + } else { + try { + val uninstantiated = new ListBuffer[Symbol]; + val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated); + val result = ( + exprTypeArgs(uninstantiated.toList, restpe.subst(undetparams, targs), pt) != null && + isWithinBounds(undetparams, targs) ); - result - } catch { - case ex: NoInstance => false - } - } - case PolyType(tparams, restpe) => - val tparams1 = cloneSymbols(tparams); - isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes, pt) - case ErrorType => - true - case _ => - false + result + } catch { + case ex: NoInstance => false + } + } + case PolyType(tparams, restpe) => + val tparams1 = cloneSymbols(tparams); + isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes, pt) + case ErrorType => + true + case _ => + false } /** Does type `ftpe1' specialize type `ftpe2' * when both are alternatives in an overloaded function? */ def specializes(ftpe1: Type, ftpe2: Type): boolean = ftpe1 match { case MethodType(formals, _) => - isApplicable(List(), ftpe2, formals, WildcardType) + isApplicable(List(), ftpe2, formals, WildcardType) case PolyType(tparams, MethodType(formals, _)) => - isApplicable(List(), ftpe2, formals, WildcardType) + isApplicable(List(), ftpe2, formals, WildcardType) case ErrorType => - true + true case _ => - false + false } /** Is type `tpe1' a strictly better alternative than type `ftpe2'? */ @@ -433,10 +433,11 @@ trait Infer requires Analyzer { /** error if arguments not within bounds. */ def checkBounds(pos: int, tparams: List[Symbol], targs: List[Type], prefix: String): unit = if (!isWithinBounds(tparams, targs)) { - error(pos, - prefix + "type arguments " + targs.mkString("[", ",", "]") + - " do not conform to " + tparams.head.owner + "'s type parameter bounds " + - (tparams map (.defString)).mkString("[", ",", "]")); + if (!(targs exists (.isErroneous)) && !(tparams exists (.isErroneous))) + error(pos, + prefix + "type arguments " + targs.mkString("[", ",", "]") + + " do not conform to " + tparams.head.owner + "'s type parameter bounds " + + (tparams map (.defString)).mkString("[", ",", "]")); if (settings.explaintypes.value) { val bounds = tparams map (.info.subst(tparams, targs).bounds); List.map2(targs, bounds)((targ, bound) => explainTypes(bound.lo, targ)); @@ -467,37 +468,38 @@ trait Infer requires Analyzer { * `targs', Error if `targs' is null */ private def substExpr(tree: Tree, undetparams: List[Symbol], targs: List[Type], pt: Type): unit = if (targs == null) { - error(tree.pos, "polymorphic expression cannot be instantiated to expected type" + - foundReqMsg(PolyType(undetparams, skipImplicit(tree.tpe)), pt)); + if (!tree.tpe.isErroneous && !pt.isErroneous) + error(tree.pos, "polymorphic expression cannot be instantiated to expected type" + + foundReqMsg(PolyType(undetparams, skipImplicit(tree.tpe)), pt)); } else { - checkBounds(tree.pos, undetparams, targs, "inferred "); - new TreeTypeSubstituter(undetparams, targs).traverse(tree); + checkBounds(tree.pos, undetparams, targs, "inferred "); + new TreeTypeSubstituter(undetparams, targs).traverse(tree); } /** Substitite free type variables `undetparams' of application `fn(args)', given prototype `pt'. * Return the list of type parameters that remain uninstantiated. */ def inferMethodInstance(fn: Tree, undetparams: List[Symbol], args: List[Tree], pt: Type): List[Symbol] = fn.tpe match { case MethodType(formals, restpe) => - try { - val argtpes = args map (.tpe.deconst); - val uninstantiated = new ListBuffer[Symbol]; - val targs = methTypeArgs( - undetparams, formalTypes(formals, argtpes.length), restpe, argtpes, pt, uninstantiated); - checkBounds(fn.pos, undetparams, targs, "inferred "); - val treeSubst = new TreeTypeSubstituter(undetparams, targs); - treeSubst.traverse(fn); - treeSubst.traverseTrees(args); - uninstantiated.toList; - } catch { - case ex: NoInstance => - errorTree(fn, - "no type parameters for " + - applyErrorMsg( - fn, " exist so that it can be applied to arguments ", - args map (.tpe.widen), WildcardType) + - "\n --- because ---\n" + ex.getMessage()); - List() - } + try { + val argtpes = args map (.tpe.deconst); + val uninstantiated = new ListBuffer[Symbol]; + val targs = methTypeArgs( + undetparams, formalTypes(formals, argtpes.length), restpe, argtpes, pt, uninstantiated); + checkBounds(fn.pos, undetparams, targs, "inferred "); + val treeSubst = new TreeTypeSubstituter(undetparams, targs); + treeSubst.traverse(fn); + treeSubst.traverseTrees(args); + uninstantiated.toList; + } catch { + case ex: NoInstance => + errorTree(fn, + "no type parameters for " + + applyErrorMsg( + fn, " exist so that it can be applied to arguments ", + args map (.tpe.widen), WildcardType) + + "\n --- because ---\n" + ex.getMessage()); + List() + } } /** Substitite free type variables `undetparams' of type constructor `tree' in pattern, @@ -510,53 +512,53 @@ trait Infer requires Analyzer { /** Compute type arguments for undetermined params and substitute them in given tree. */ def computeArgs = - try { - val targs = solve(tvars, undetparams, undetparams map varianceInType(restpe), true); + try { + val targs = solve(tvars, undetparams, undetparams map varianceInType(restpe), true); checkBounds(tree.pos, undetparams, targs, "inferred "); - new TreeTypeSubstituter(undetparams, targs).traverse(tree) - } catch { - case ex: NoInstance => + new TreeTypeSubstituter(undetparams, targs).traverse(tree) + } catch { + case ex: NoInstance => errorTree(tree, "constructor of type " + restpe + - " can be instantiated in more than one way to expected type " + pt + - "\n --- because ---\n" + ex.getMessage()); - } + " can be instantiated in more than one way to expected type " + pt + + "\n --- because ---\n" + ex.getMessage()); + } def instError = { - if (settings.debug.value) System.out.println("ici " + tree + " " + undetparams + " " + pt); - if (settings.explaintypes.value) explainTypes(restpe.subst(undetparams, tvars), pt); + if (settings.debug.value) System.out.println("ici " + tree + " " + undetparams + " " + pt); + if (settings.explaintypes.value) explainTypes(restpe.subst(undetparams, tvars), pt); errorTree(tree, "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt)) } if (restpe.subst(undetparams, tvars) <:< pt) { - computeArgs + computeArgs } else if (isFullyDefined(pt)) { - if (settings.debug.value) log("infer constr " + tree + ":" + restpe + ", pt = " + pt); - val ptparams = freeTypeParams.collect(pt); - if (settings.debug.value) log("free type params = " + ptparams); - val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType)); + if (settings.debug.value) log("infer constr " + tree + ":" + restpe + ", pt = " + pt); + val ptparams = freeTypeParams.collect(pt); + if (settings.debug.value) log("free type params = " + ptparams); + val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType)); tvars = undetparams map freshVar; - if (restpe.subst(undetparams, tvars) <:< ptWithWildcards) { - computeArgs; - restpe = skipImplicit(tree.tpe.resultType); - if (settings.debug.value) log("new tree = " + tree + ":" + restpe); - val ptvars = ptparams map freshVar; - if (restpe <:< pt.subst(ptparams, ptvars)) { - for (val tvar <- ptvars) { - val tparam = tvar.origin.symbol; - val Pair(loBounds, hiBounds) = - if (tvar.constr.inst != NoType && isFullyDefined(tvar.constr.inst)) - Pair(List(tvar.constr.inst), List(tvar.constr.inst)) - else - Pair(tvar.constr.lobounds, tvar.constr.hibounds); - if (!loBounds.isEmpty || !hiBounds.isEmpty) { + if (restpe.subst(undetparams, tvars) <:< ptWithWildcards) { + computeArgs; + restpe = skipImplicit(tree.tpe.resultType); + if (settings.debug.value) log("new tree = " + tree + ":" + restpe); + val ptvars = ptparams map freshVar; + if (restpe <:< pt.subst(ptparams, ptvars)) { + for (val tvar <- ptvars) { + val tparam = tvar.origin.symbol; + val Pair(loBounds, hiBounds) = + if (tvar.constr.inst != NoType && isFullyDefined(tvar.constr.inst)) + Pair(List(tvar.constr.inst), List(tvar.constr.inst)) + else + Pair(tvar.constr.lobounds, tvar.constr.hibounds); + if (!loBounds.isEmpty || !hiBounds.isEmpty) { context.nextEnclosing(.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam); - tparam setInfo TypeBounds( - lub(tparam.info.bounds.lo :: loBounds), - glb(tparam.info.bounds.hi :: hiBounds)); - if (settings.debug.value) log("new bounds of " + tparam + " = " + tparam.info); - } - } - } else { if (settings.debug.value) System.out.println("no instance: "); instError } - } else { if (settings.debug.value) System.out.println("not a subtype " + restpe.subst(undetparams, tvars) + " of " + ptWithWildcards); instError } + tparam setInfo TypeBounds( + lub(tparam.info.bounds.lo :: loBounds), + glb(tparam.info.bounds.hi :: hiBounds)); + if (settings.debug.value) log("new bounds of " + tparam + " = " + tparam.info); + } + } + } else { if (settings.debug.value) System.out.println("no instance: "); instError } + } else { if (settings.debug.value) System.out.println("not a subtype " + restpe.subst(undetparams, tvars) + " of " + ptWithWildcards); instError } } else { if (settings.debug.value) System.out.println("not fuly defined: " + pt); instError } } @@ -571,10 +573,10 @@ trait Infer requires Analyzer { override def traverse(tp: Type): TypeTraverser = { tp match { case TypeRef(NoPrefix, sym, _) => - includeIfTypeParam(sym) - case TypeRef(ThisType(_), sym, _) => - includeIfTypeParam(sym) - case _ => + includeIfTypeParam(sym) + case TypeRef(ThisType(_), sym, _) => + includeIfTypeParam(sym) + case _ => } mapOver(tp); this @@ -596,38 +598,38 @@ trait Infer requires Analyzer { */ def inferExprAlternative(tree: Tree, pt: Type): unit = tree.tpe match { case OverloadedType(pre, alts) => tryTwice { - var alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt)); + var alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt)); if (alts1.isEmpty) alts1 = alts; - def improves(sym1: Symbol, sym2: Symbol): boolean = ( - sym2 == NoSymbol || - ((sym1.owner isSubClass sym2.owner) && - {val tp1 = pre.memberType(sym1); - val tp2 = pre.memberType(sym2); - (tp2 == ErrorType || - !global.typer.infer.isCompatible(tp2, pt) && global.typer.infer.isCompatible(tp1, pt) || + def improves(sym1: Symbol, sym2: Symbol): boolean = ( + sym2 == NoSymbol || + ((sym1.owner isSubClass sym2.owner) && + {val tp1 = pre.memberType(sym1); + val tp2 = pre.memberType(sym2); + (tp2 == ErrorType || + !global.typer.infer.isCompatible(tp2, pt) && global.typer.infer.isCompatible(tp1, pt) || isStrictlyBetter(tp1, tp2)) }) ); - val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) => - if (improves(alt, best)) alt else best); - val competing = alts1 dropWhile (alt => best == alt || improves(best, alt)); - if (best == NoSymbol) { + val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) => + if (improves(alt, best)) alt else best); + val competing = alts1 dropWhile (alt => best == alt || improves(best, alt)); + if (best == NoSymbol) { if (settings.debug.value) { - tree match { - case Select(qual, _) => - System.out.println("qual: " + qual + ":" + qual.tpe + " with decls " + qual.tpe.decls + " with members " + qual.tpe.members + " with members " + qual.tpe.member(newTermName("$minus"))); - case _ => - } + tree match { + case Select(qual, _) => + System.out.println("qual: " + qual + ":" + qual.tpe + " with decls " + qual.tpe.decls + " with members " + qual.tpe.members + " with members " + qual.tpe.member(newTermName("$minus"))); + case _ => + } } - typeErrorTree(tree, tree.symbol.tpe, pt) - } else if (!competing.isEmpty) { - if (!pt.isError) - context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt); - setError(tree); + typeErrorTree(tree, tree.symbol.tpe, pt) + } else if (!competing.isEmpty) { + if (!pt.isErroneous) + context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt); + setError(tree); () - } else { - tree.setSymbol(best).setType(pre.memberType(best)) - } + } else { + tree.setSymbol(best).setType(pre.memberType(best)) + } } } @@ -641,32 +643,32 @@ trait Infer requires Analyzer { */ def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): unit = tree.tpe match { case OverloadedType(pre, alts) => tryTwice { - if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt); - val applicable = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt)); - def improves(sym1: Symbol, sym2: Symbol) = ( - sym2 == NoSymbol || sym2.isError || - ((sym1.owner isSubClass sym2.owner) && - specializes(pre.memberType(sym1), pre.memberType(sym2))) - ); - val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) => - if (improves(alt, best)) alt else best); - val competing = applicable dropWhile (alt => best == alt || improves(best, alt)); - if (best == NoSymbol) { - if (pt == WildcardType) { - errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)) - } else { - inferMethodAlternative(tree, undetparams, argtpes, WildcardType) - } - } else if (!competing.isEmpty) { - if (!(argtpes exists (.isError)) && !pt.isError) - context.ambiguousError(tree.pos, pre, best, competing.head, - "argument types " + argtpes.mkString("(", ",", ")") + - (if (pt == WildcardType) "" else " and expected result type " + pt)); - setError(tree); - () - } else { - tree.setSymbol(best).setType(pre.memberType(best)) - } + if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt); + val applicable = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt)); + def improves(sym1: Symbol, sym2: Symbol) = ( + sym2 == NoSymbol || sym2.isError || + ((sym1.owner isSubClass sym2.owner) && + specializes(pre.memberType(sym1), pre.memberType(sym2))) + ); + val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) => + if (improves(alt, best)) alt else best); + val competing = applicable dropWhile (alt => best == alt || improves(best, alt)); + if (best == NoSymbol) { + if (pt == WildcardType) { + errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)) + } else { + inferMethodAlternative(tree, undetparams, argtpes, WildcardType) + } + } else if (!competing.isEmpty) { + if (!(argtpes exists (.isErroneous)) && !pt.isErroneous) + context.ambiguousError(tree.pos, pre, best, competing.head, + "argument types " + argtpes.mkString("(", ",", ")") + + (if (pt == WildcardType) "" else " and expected result type " + pt)); + setError(tree); + () + } else { + tree.setSymbol(best).setType(pre.memberType(best)) + } } } @@ -675,18 +677,18 @@ trait Infer requires Analyzer { def tryTwice(infer: => unit): unit = { if (context.implicitsEnabled) { val reportGeneralErrors = context.reportGeneralErrors; - context.reportGeneralErrors = false; - context.implicitsEnabled = false; - try { - infer - } catch { - case ex: TypeError => - context.reportGeneralErrors = reportGeneralErrors; - context.implicitsEnabled = true; - infer - } - context.reportGeneralErrors = reportGeneralErrors - context.implicitsEnabled = true + context.reportGeneralErrors = false; + context.implicitsEnabled = false; + try { + infer + } catch { + case ex: TypeError => + context.reportGeneralErrors = reportGeneralErrors; + context.implicitsEnabled = true; + infer + } + context.reportGeneralErrors = reportGeneralErrors + context.implicitsEnabled = true } else infer } @@ -696,22 +698,22 @@ trait Infer requires Analyzer { */ def inferPolyAlternatives(tree: Tree, nparams: int): unit = tree.tpe match { case OverloadedType(pre, alts) => - val sym = tree.symbol filter (alt => alt.typeParams.length == nparams); - if (sym == NoSymbol) { - errorTree(tree, - if (alts exists (alt => alt.typeParams.length > 0)) - "wrong number of type parameters for " + treeSymTypeMsg(tree) - else treeSymTypeMsg(tree) + " does not take type parameters") - } else if (sym.hasFlag(OVERLOADED)) { - val tparams = sym.alternatives.head.typeParams; - val tpe = - PolyType(tparams, - OverloadedType(AntiPolyType(pre, tparams map (.tpe)), sym.alternatives)); - sym.setInfo(tpe); - tree.setSymbol(sym).setType(tpe); - } else { - tree.setSymbol(sym).setType(pre.memberType(sym)) - } + val sym = tree.symbol filter (alt => alt.typeParams.length == nparams); + if (sym == NoSymbol) { + errorTree(tree, + if (alts exists (alt => alt.typeParams.length > 0)) + "wrong number of type parameters for " + treeSymTypeMsg(tree) + else treeSymTypeMsg(tree) + " does not take type parameters") + } else if (sym.hasFlag(OVERLOADED)) { + val tparams = sym.alternatives.head.typeParams; + val tpe = + PolyType(tparams, + OverloadedType(AntiPolyType(pre, tparams map (.tpe)), sym.alternatives)); + sym.setInfo(tpe); + tree.setSymbol(sym).setType(tpe); + } else { + tree.setSymbol(sym).setType(pre.memberType(sym)) + } } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1398b95e35..3e93ca194c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -142,7 +142,7 @@ trait Typers requires Analyzer { /** Check that tree is a stable expression. */ def checkStable(tree: Tree): Tree = - if (treeInfo.isPureExpr(tree) || tree.tpe.isError) tree + if (treeInfo.isPureExpr(tree)) tree else errorTree(tree, "stable identifier required, but "+tree+" found.") /** Check that type `tp' is not a subtype of itself. @@ -225,9 +225,10 @@ trait Typers requires Analyzer { apply(tree.tpe) if (badSymbol == NoSymbol) tree else { - error(tree.pos, - (if (badSymbol.hasFlag(PRIVATE)) "private " else "") + badSymbol + - " escapes its defining scope as part of type "+tree.tpe) + if (!badSymbol.isErroneous) + error(tree.pos, + (if (badSymbol.hasFlag(PRIVATE)) "private " else "") + badSymbol + + " escapes its defining scope as part of type "+tree.tpe) setError(tree) } } @@ -372,7 +373,7 @@ trait Typers requires Analyzer { } else tree typed(applyImplicitArgs(tree1), mode, pt) case mt: MethodType - if (((mode & (EXPRmode | FUNmode)) == EXPRmode) && + if (((mode & (EXPRmode | FUNmode | LHSmode)) == 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) @@ -381,15 +382,14 @@ trait Typers requires Analyzer { typed(etaExpand(tree), mode, pt) } else if (!tree.symbol.isConstructor && mt.paramTypes.isEmpty) { // (4.3) adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt) + } else if (context.implicitsEnabled) { + if (settings.migrate.value && !tree.symbol.isConstructor && isCompatible(mt, pt)) + errorTree(tree, migrateMsg + " method can be converted to function only if an expected function type is given"); + else + errorTree(tree, "missing arguments for "+tree.symbol+tree.symbol.locationString+ + (if (tree.symbol.isConstructor) "" + else ";\nprefix this method with `&' if you want to treat it as a partially applied function")) } else { - if (context.implicitsEnabled) { - if (settings.migrate.value && !tree.symbol.isConstructor && isCompatible(mt, pt)) - error(tree.pos, migrateMsg + " method can be converted to function only if an expected function type is given"); - else - error(tree.pos, "missing arguments for "+tree.symbol+tree.symbol.locationString+ - (if (tree.symbol.isConstructor) "" - else ";\nprefix this method with `&' if you want to treat it as a partially applied function")) - } setError(tree) } case _ => @@ -427,9 +427,7 @@ trait Typers requires Analyzer { setError(tree) } } else { - if (!tree.tpe.isError) - error(tree.pos, ""+clazz+" is neither a case class nor a sequence class") - setError(tree) + errorTree(tree, ""+clazz+" is neither a case class nor a sequence class") } } } else if ((mode & FUNmode) != 0) { @@ -968,7 +966,8 @@ trait Typers requires Analyzer { while (e1 != null && e1.owner == scope) { if (!e1.sym.hasFlag(LOCAL) && (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe))) - error(e.sym.pos, ""+e1.sym+" is defined twice"); + if (!e.sym.isErroneous && !e1.sym.isErroneous) + error(e.sym.pos, ""+e1.sym+" is defined twice"); e1 = scope.lookupNextEntry(e1); } } @@ -1142,13 +1141,14 @@ trait Typers requires Analyzer { } if (sym.info == NoType) { if (settings.debug.value) System.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.symbol+"\nsymbol-info = "+qual.tpe.symbol.info+"\nscope-id = "+qual.tpe.symbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nfound = "+sym) - if (!qual.tpe.widen.isError) + if (!qual.tpe.widen.isErroneous) { if (context.unit == null) assert(false, "("+qual+":"+qual.tpe+")."+name) error(tree.pos, decode(name)+" is not a member of "+qual.tpe.widen + (if (Position.line(context.unit.source, qual.pos) < Position.line(context.unit.source, tree.pos)) "\npossible cause: maybe a semicolon is missing before `"+name+"'?" else "")) + } setError(tree) } else { val tree1 = tree match { |