summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-04-11 16:22:28 +0000
committerMartin Odersky <odersky@gmail.com>2006-04-11 16:22:28 +0000
commite3fc3506c7c918aba5cc7c3baabca95de8f6ac4c (patch)
tree67c1ec643f9b418914e0f82341785cd7860d77d1
parenta0c48ce649c3d320623a3369b8ade2665b71f613 (diff)
downloadscala-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
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala9
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala58
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala19
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala574
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala36
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 {