summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala347
1 files changed, 200 insertions, 147 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 1d6f1bddac..284b12e501 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -12,9 +12,9 @@ package scala.tools.nsc
package typechecker
import scala.collection.mutable.{HashMap, ListBuffer}
-import scala.util.control.ControlException
+import scala.util.control.ControlThrowable
import scala.tools.nsc.interactive.RangePositions
-import scala.tools.nsc.util.{ Position, Set, NoPosition, SourceFile, BatchSourceFile }
+import scala.tools.nsc.util.{Set, SourceFile, BatchSourceFile}
import symtab.Flags._
import util.Statistics
@@ -135,21 +135,31 @@ trait Typers { self: Analyzer =>
*/
val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode
+ /** The mode <code>BYVALmode</code> is set when we are typing an expression
+ * that occurs in a by-value position. An expression e1 is in by-value
+ * position within expression e2 iff it will be reduced to a value at that
+ * position during the evaluation of e2. Examples are by-value function
+ * arguments or the conditional of an if-then-else clause.
+ * This mode has been added to support continuations.
+ */
+ val BYVALmode = 0x8000
+
/** The mode <code>TYPEPATmode</code> is set when we are typing a type in a pattern
*/
val TYPEPATmode = 0x10000
private val stickyModes: Int = EXPRmode | PATTERNmode | TYPEmode | ALTmode
- private def funMode(mode: Int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode
+ private def funMode(mode: Int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode | BYVALmode
private def typeMode(mode: Int) =
if ((mode & (PATTERNmode | TYPEPATmode)) != 0) TYPEmode | TYPEPATmode
else TYPEmode
- private def argMode(fun: Tree, mode: Int) =
+ private def argMode(fun: Tree, mode: Int) = {
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode
else mode
+ }
abstract class Typer(context0: Context) {
import context0.unit
@@ -198,7 +208,7 @@ trait Typers { self: Analyzer =>
s traverse fun
for (arg <- args) s traverse arg
}
- Apply(fun, args) setPos fun.pos
+ new ApplyToImplicitArgs(fun, args) setPos fun.pos
case ErrorType =>
fun
}
@@ -334,7 +344,7 @@ trait Typers { self: Analyzer =>
tp match {
case TypeRef(pre, sym, args) =>
(checkNotLocked(sym)) && (
- !sym.isTypeMember ||
+ !sym.isNonClassType ||
checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym) // @M! info for a type ref to a type parameter now returns a polytype
// @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym)
)
@@ -439,13 +449,13 @@ trait Typers { self: Analyzer =>
check(owner, scope, pt, tree setType tp1.typeSymbol.classBound)
else if (owner == NoSymbol)
tree setType packSymbols(hiddenSymbols.reverse, tp1)
- else { // privates
+ else if (!phase.erasedTypes) { // privates
val badSymbol = hiddenSymbols.head
error(tree.pos,
(if (badSymbol hasFlag PRIVATE) "private " else "") + badSymbol +
" escapes its defining scope as part of type "+tree.tpe)
setError(tree)
- }
+ } else tree
}
def addHidden(sym: Symbol) =
@@ -553,7 +563,7 @@ trait Typers { self: Analyzer =>
sym.rawInfo.isInstanceOf[loaders.ClassfileLoader] && {
sym.rawInfo.load(sym)
(sym.sourceFile ne null) &&
- (currentRun.compiledFiles contains sym.sourceFile)
+ (currentRun.compiledFiles contains sym.sourceFile.path)
}
}
@@ -632,16 +642,15 @@ trait Typers { self: Analyzer =>
* </ol>
*/
private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = {
- def isNotAValue(sym: Symbol) = // bug #1392
- !sym.isValue || (sym.isModule && isValueClass(sym.linkedClassOfModule))
-
if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0)
inferExprAlternative(tree, pt)
val sym = tree.symbol
+
if (tree.tpe.isError) tree
else if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) { // (1)
- checkStable(tree)
- } else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && isNotAValue(sym) && !phase.erasedTypes) { // (2)
+ if (sym.isValue) checkStable(tree)
+ else errorTree(tree, sym+" is not a value")
+ } else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue && !phase.erasedTypes) { // (2)
errorTree(tree, sym+" is not a value")
} else {
if (sym.isStable && pre.isStable && tree.tpe.typeSymbol != ByNameParamClass &&
@@ -768,7 +777,7 @@ trait Typers { self: Analyzer =>
* (5) Convert constructors in a pattern as follows:
* (5.1) If constructor refers to a case class factory, set tree's type to the unique
* instance of its primary constructor that is a subtype of the expected type.
- * (5.2) If constructor refers to an exractor, convert to application of
+ * (5.2) If constructor refers to an extractor, convert to application of
* unapply or unapplySeq method.
*
* (6) Convert all other types to TypeTree nodes.
@@ -781,7 +790,8 @@ trait Typers { self: Analyzer =>
* is an integer fitting in the range of that type, convert it to that type.
* (11) Widen numeric literals to their expected type, if necessary
* (12) When in mode EXPRmode, convert E to { E; () } if expected type is scala.Unit.
- * (13) When in mode EXPRmode, apply a view
+ * (13) When in mode EXPRmode, apply AnnotationChecker conversion if expected type is annotated.
+ * (14) When in mode EXPRmode, apply a view
* If all this fails, error
*/
protected def adapt(tree: Tree, mode: Int, pt: Type, original: Tree = EmptyTree): Tree = tree.tpe match {
@@ -817,7 +827,7 @@ trait Typers { self: Analyzer =>
TypeTree(tparam.tpeHK) setPos tree.pos.focus)) setPos tree.pos //@M/tcpolyinfer: changed tparam.tpe to tparam.tpeHK
context.undetparams = context.undetparams ::: tparams1
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original)
- case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1)
+ case mt: MethodType if mt.isImplicit && ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1)
if (!context.undetparams.isEmpty/* && (mode & POLYmode) == 0 disabled to make implicits in new collection work; we should revisit this. */) { // (9)
// println("adapt IMT: "+(context.undetparams, pt)) //@MDEBUG
context.undetparams = inferExprInstance(
@@ -888,7 +898,7 @@ trait Typers { self: Analyzer =>
!(tree.symbol.hasFlag(JAVA) && context.unit.isJava)) { // (7)
// @M When not typing a higher-kinded type ((mode & HKmode) == 0)
// or raw type (tree.symbol.hasFlag(JAVA) && context.unit.isJava), types must be of kind *,
- // and thus parameterised types must be applied to their type arguments
+ // and thus parameterized types must be applied to their type arguments
// @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
errorTree(tree, tree.symbol+" takes type parameters")
tree setType tree.tpe
@@ -977,13 +987,15 @@ trait Typers { self: Analyzer =>
return typed(atPos(tree.pos)(Block(List(tree), Literal(()))), mode, pt)
else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt))
return typed(atPos(tree.pos)(Select(tree, "to"+sym.name)), mode, pt)
+ case AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (13)
+ return typed(adaptAnnotations(tree, mode, pt), mode, pt)
case _ =>
}
if (!context.undetparams.isEmpty) {
return instantiate(tree, mode, pt)
}
if (context.implicitsEnabled && !tree.tpe.isError && !pt.isError) {
- // (13); the condition prevents chains of views
+ // (14); the condition prevents chains of views
if (settings.debug.value) log("inferring view from "+tree.tpe+" to "+pt)
val coercion = inferView(tree, tree.tpe, pt, true)
// convert forward views of delegate types into closures wrapped around
@@ -997,7 +1009,7 @@ trait Typers { self: Analyzer =>
if (coercion != EmptyTree) {
if (settings.debug.value) log("inferred view from "+tree.tpe+" to "+pt+" = "+coercion+":"+coercion.tpe)
return newTyper(context.makeImplicit(context.reportAmbiguousErrors)).typed(
- Apply(coercion, List(tree)) setPos tree.pos, mode, pt)
+ new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt)
}
}
}
@@ -1027,6 +1039,7 @@ trait Typers { self: Analyzer =>
((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) &&
phase.id <= currentRun.typerPhase.id && !qtpe.isError &&
qtpe.typeSymbol != NullClass && qtpe.typeSymbol != NothingClass && qtpe != WildcardType &&
+ !qual.isInstanceOf[ApplyImplicitView] && // don't chain views
context.implicitsEnabled) { // don't try to adapt a top-level type that's the subject of an implicit search
// this happens because, if isView, typedImplicit tries to apply the "current" implicit value to
// a value that needs to be coerced, so we check whether the implicit value has an `apply` method
@@ -1038,7 +1051,7 @@ trait Typers { self: Analyzer =>
}
val coercion = inferView(qual, qtpe, searchTemplate, true)
if (coercion != EmptyTree)
- typedQualifier(atPos(qual.pos)(Apply(coercion, List(qual))))
+ typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual))))
else
qual
} else {
@@ -1255,9 +1268,9 @@ trait Typers { self: Analyzer =>
/*
if (settings.Xshowcls.value != "" &&
- settings.Xshowcls.value == context.owner.fullNameString)
+ settings.Xshowcls.value == context.owner.fullName)
println("INFO "+context.owner+
- ", baseclasses = "+(context.owner.info.baseClasses map (_.fullNameString))+
+ ", baseclasses = "+(context.owner.info.baseClasses map (_.fullName))+
", lin = "+(context.owner.info.baseClasses map (context.owner.thisType.baseType)))
*/
}
@@ -1314,7 +1327,7 @@ trait Typers { self: Analyzer =>
// attributes(mdef)
// initialize all constructors of the linked class: the type completer (Namer.methodSig)
// might add default getters to this object. example: "object T; class T(x: Int = 1)"
- val linkedClass = mdef.symbol.linkedClassOfModule
+ val linkedClass = mdef.symbol.companionClass
if (linkedClass != NoSymbol)
for (c <- linkedClass.info.decl(nme.CONSTRUCTOR).alternatives)
c.initialize
@@ -1476,6 +1489,8 @@ trait Typers { self: Analyzer =>
*/
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
val clazz = context.owner
+ // complete lazy annotations
+ val annots = clazz.annotations
if (templ.symbol == NoSymbol)
templ setSymbol clazz.newLocalDummy(templ.pos)
val self1 = templ.self match {
@@ -1490,7 +1505,7 @@ trait Typers { self: Analyzer =>
// val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
// treeCopy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType
// but this leads to cycles for existential self types ==> #2545
- if (self1.name != nme.WILDCARD) context.scope enter self1.symbol
+ if (self1.name != nme.WILDCARD) context.scope enter self1.symbol
val selfType =
if (clazz.isAnonymousClass && !phase.erasedTypes)
intersectionType(clazz.info.parents, clazz.owner)
@@ -1530,6 +1545,9 @@ trait Typers { self: Analyzer =>
val typer1 = constrTyperIf(sym.hasFlag(PARAM) && sym.owner.isConstructor)
val typedMods = removeAnnotations(vdef.mods)
+ // complete lazy annotations
+ val annots = sym.annotations
+
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
checkNonCyclic(vdef, tpt1)
if (sym.hasAnnotation(definitions.VolatileAttr)) {
@@ -1545,7 +1563,7 @@ trait Typers { self: Analyzer =>
vdef.rhs
} else {
val tpt2 = if (sym hasFlag DEFAULTPARAM) {
- // When typechecking default parameter, replace all type parameters in the expected type by Wildcarad.
+ // When typechecking default parameter, replace all type parameters in the expected type by Wildcard.
// This allows defining "def foo[T](a: T = 1)"
val tparams =
if (sym.owner.isConstructor) sym.owner.owner.info.typeParams
@@ -1558,11 +1576,11 @@ trait Typers { self: Analyzer =>
}
// allow defaults on by-name parameters
if (sym hasFlag BYNAMEPARAM)
- if (tpt1.tpe.typeArgs.isEmpty) WildcardType // during erasure tpt1 is Funciton0
+ if (tpt1.tpe.typeArgs.isEmpty) WildcardType // during erasure tpt1 is Function0
else subst(tpt1.tpe.typeArgs(0))
else subst(tpt1.tpe)
} else tpt1.tpe
- newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt2)
+ newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, EXPRmode | BYVALmode, tpt2)
}
treeCopy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
@@ -1800,6 +1818,9 @@ trait Typers { self: Analyzer =>
val tparams1 = ddef.tparams mapConserve typedTypeDef
val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef)
+ // complete lazy annotations
+ val annots = meth.annotations
+
for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
if (isRepeatedParamType(vparam1.symbol.tpe))
error(vparam1.pos, "*-parameter must come last")
@@ -1824,7 +1845,7 @@ trait Typers { self: Analyzer =>
error(ddef.pos, "constructor definition not allowed here")
typed(ddef.rhs)
} else {
- transformedOrTyped(ddef.rhs, tpt1.tpe)
+ transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe)
}
if (meth.isPrimaryConstructor && meth.isClassConstructor &&
@@ -1845,6 +1866,8 @@ trait Typers { self: Analyzer =>
reenterTypeParams(tdef.tparams) // @M!
val tparams1 = tdef.tparams mapConserve (typedTypeDef) // @M!
val typedMods = removeAnnotations(tdef.mods)
+ // complete lazy annotations
+ val annots = tdef.symbol.annotations
val rhs1 = checkNoEscaping.privates(tdef.symbol, typedType(tdef.rhs))
checkNonCyclic(tdef.symbol)
if (tdef.symbol.owner.isType)
@@ -1867,11 +1890,31 @@ trait Typers { self: Analyzer =>
}
}
+ private def isLoopHeaderLabel(name: Name): Boolean =
+ name.startsWith("while$") || name.startsWith("doWhile$")
+
def typedLabelDef(ldef: LabelDef): LabelDef = {
- val restpe = ldef.symbol.tpe.resultType
- val rhs1 = typed(ldef.rhs, restpe)
- ldef.params foreach (param => param.tpe = param.symbol.tpe)
- treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
+ if (!isLoopHeaderLabel(ldef.symbol.name) || phase.id > currentRun.typerPhase.id) {
+ val restpe = ldef.symbol.tpe.resultType
+ val rhs1 = typed(ldef.rhs, restpe)
+ ldef.params foreach (param => param.tpe = param.symbol.tpe)
+ treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
+ } else {
+ val initpe = ldef.symbol.tpe.resultType
+ val rhs1 = typed(ldef.rhs)
+ val restpe = rhs1.tpe
+ if (restpe == initpe) { // stable result, no need to check again
+ ldef.params foreach (param => param.tpe = param.symbol.tpe)
+ treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
+ } else {
+ context.scope.unlink(ldef.symbol)
+ val sym2 = namer.enterInScope(
+ context.owner.newLabel(ldef.pos, ldef.name) setInfo MethodType(List(), restpe))
+ val rhs2 = typed(resetAllAttrs(ldef.rhs), restpe)
+ ldef.params foreach (param => param.tpe = param.symbol.tpe)
+ treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs2) setSymbol sym2 setType restpe
+ }
+ }
}
protected def typedFunctionIDE(fun : Function, txt : Context) = {}
@@ -1991,7 +2034,7 @@ trait Typers { self: Analyzer =>
||
pt.typeSymbol == PartialFunctionClass &&
fun.vparams.length == 1 && fun.body.isInstanceOf[Match])
- && // see bug901 for a reason why next conditions are neeed
+ && // see bug901 for a reason why next conditions are needed
(pt.normalize.typeArgs.length - 1 == fun.vparams.length
||
fun.vparams.exists(_.tpt.isEmpty)))
@@ -2095,7 +2138,7 @@ trait Typers { self: Analyzer =>
} else {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
- val result = checkDead(localTyper.typed(stat))
+ val result = checkDead(localTyper.typed(stat, EXPRmode | BYVALmode, WildcardType))
if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.pointOrElse(0) >= exprOwner.enclMethod.pos.pointOrElse(0))
@@ -2175,11 +2218,11 @@ trait Typers { self: Analyzer =>
args mapConserve (arg => typedArg(arg, mode, 0, WildcardType))
def typedArgs(args: List[Tree], mode: Int, originalFormals: List[Type], adaptedFormals: List[Type]) = {
- def newmode(i: Int) =
- if (isVarArgTpes(originalFormals) && i >= originalFormals.length - 1) STARmode else 0
-
- for (((arg, formal), i) <- (args zip adaptedFormals).zipWithIndex) yield
- typedArg(arg, mode, newmode(i), formal)
+ var newmodes = originalFormals map ((tp: Type) => if (tp.typeSymbol != ByNameParamClass) BYVALmode else 0)
+ if (isVarArgTpes(originalFormals)) // TR check really necessary?
+ newmodes = newmodes.take(newmodes.length-1) ::: List.fill(args.length - originalFormals.length + 1)(STARmode | BYVALmode)
+ for (((arg, formal), m) <- ((args zip adaptedFormals) zip newmodes)) yield
+ typedArg(arg, mode, m, formal)
}
/** Does function need to be instantiated, because a missing parameter
@@ -2257,12 +2300,12 @@ trait Typers { self: Analyzer =>
val args1 = args map {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
// named args: only type the righthand sides ("unknown identifier" errors otherwise)
- val rhs1 = typedArg(rhs, amode, 0, WildcardType)
+ val rhs1 = typedArg(rhs, amode, BYVALmode, WildcardType)
argtpes += NamedType(name, rhs1.tpe.deconst)
// the assign is untyped; that's ok because we call doTypedApply
atPos(arg.pos) { new AssignOrNamedArg(arg.lhs , rhs1) }
case arg =>
- val arg1 = typedArg(arg, amode, 0, WildcardType)
+ val arg1 = typedArg(arg, amode, BYVALmode, WildcardType)
argtpes += arg1.tpe.deconst
arg1
}
@@ -2346,7 +2389,7 @@ trait Typers { self: Analyzer =>
true
case _ => false
}
- val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, params, fun.pos.focus)
+ val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, params, fun.pos.focus, context)
if (allArgs.length == formals.length) {
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
context.diagnostic = "Error occured in an application involving default arguments." :: context.diagnostic
@@ -2425,10 +2468,15 @@ trait Typers { self: Analyzer =>
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
val strictTargs = (lenientTargs, tparams).zipped map ((targ, tparam) =>
if (targ == WildcardType) tparam.tpe else targ) //@M TODO: should probably be .tpeHK
- def typedArgToPoly(arg: Tree, formal: Type): Tree = {
+ var remainingParams = paramTypes
+ def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
+ val newmode =
+ if (remainingParams.head.typeSymbol == ByNameParamClass) POLYmode
+ else POLYmode | BYVALmode
+ if (remainingParams.tail.nonEmpty) remainingParams = remainingParams.tail
// println("typedArgToPoly(arg, formal): "+(arg, formal))
- val arg1 = typedArg(arg, argMode(fun, mode), POLYmode, lenientPt)
+ val arg1 = typedArg(arg, argMode(fun, mode), newmode, lenientPt)
val argtparams = context.extractUndetparams()
// println("typedArgToPoly(arg1, argtparams): "+(arg1, argtparams))
if (!argtparams.isEmpty) {
@@ -2483,7 +2531,7 @@ trait Typers { self: Analyzer =>
error(fun.pos, "cannot resolve overloaded unapply")
(ErrorType, List())
}
- val (unappFormal, freeVars) = freshArgType(unappType)
+ val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree))
val context1 = context.makeNewScope(context.tree, context.owner)
freeVars foreach context1.scope.enter
val typer1 = newTyper(context1)
@@ -2507,7 +2555,7 @@ trait Typers { self: Analyzer =>
//Console.println(" contains?"+sym.tpe.decls.lookup(fun.symbol.name));
if(sym != fun.symbol.owner && (sym.isPackageClass||sym.isModuleClass) /*(1)*/ ) { // (1) see 'files/pos/unapplyVal.scala'
if(fun.symbol.owner.isClass) {
- mkThisType(fun.symbol.owner)
+ ThisType(fun.symbol.owner)
} else {
//Console.println("2 ThisType("+fun.symbol.owner+")")
NoPrefix // see 'files/run/unapplyComplex.scala'
@@ -2570,13 +2618,18 @@ trait Typers { self: Analyzer =>
hasError = true
annotationError
}
- def needConst(tr: Tree): None.type = {
- error(tr.pos, "annotation argument needs to be a constant; found: "+tr)
- None
+
+ def tryConst(tr: Tree, pt: Type) = typed(tr, EXPRmode, pt) match {
+ // null cannot be used as constant value for classfile annotations
+ case l @ Literal(c) if !(l.isErroneous || c.value == null) =>
+ Some(LiteralAnnotArg(c))
+ case _ =>
+ error(tr.pos, "annotation argument needs to be a constant; found: "+tr)
+ None
}
/** Converts an untyped tree to a ClassfileAnnotArg. If the conversion fails,
- * an error message is reporded and None is returned.
+ * an error message is reported and None is returned.
*/
def tree2ConstArg(tree: Tree, pt: Type): Option[ClassfileAnnotArg] = tree match {
case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
@@ -2587,27 +2640,30 @@ trait Typers { self: Analyzer =>
None
} else Some(NestedAnnotArg(annInfo))
- // use of: object Array.apply[A <: AnyRef](args: A*): Array[A] = ...
- // and object Array.apply(args: Int*): Array[Int] = ... (and similar)
- case Apply(fun, members) =>
+ // use of Array.apply[T: ClassManifest](xs: T*): Array[T]
+ // and Array.apply(x: Int, xs: Int*): Array[Int] (and similar)
+ case Apply(fun, args) =>
val typedFun = typed(fun, funMode(mode), WildcardType)
if (typedFun.symbol.owner == ArrayModule.moduleClass &&
- typedFun.symbol.name == nme.apply &&
- pt.typeSymbol == ArrayClass &&
- !pt.typeArgs.isEmpty)
- trees2ConstArg(members, pt.typeArgs.head)
+ typedFun.symbol.name == nme.apply)
+ pt match {
+ case TypeRef(_, sym, argts) if (sym == ArrayClass && !argts.isEmpty) =>
+ trees2ConstArg(args, argts.head)
+ case _ =>
+ // For classfile annotations, pt can only be T:
+ // BT = Int, .., String, Class[_], JavaAnnotClass
+ // T = BT | Array[BT]
+ // So an array literal as argument can only be valid if pt is Array[_]
+ error(tree.pos, "found array constant, expected argument of type "+ pt)
+ None
+ }
else
- needConst(tree)
+ tryConst(tree, pt)
case Typed(t, _) => tree2ConstArg(t, pt)
- case tree => typed(tree, EXPRmode, pt) match {
- // null cannot be used as constant value for classfile annotations
- case l @ Literal(c) if !(l.isErroneous || c.value == null) =>
- Some(LiteralAnnotArg(c))
- case _ =>
- needConst(tree)
- }
+ case tree =>
+ tryConst(tree, pt)
}
def trees2ConstArg(trees: List[Tree], pt: Type): Option[ArrayAnnotArg] = {
val args = trees.map(tree2ConstArg(_, pt))
@@ -2624,7 +2680,7 @@ trait Typers { self: Analyzer =>
case Select(New(tpt), nme.CONSTRUCTOR) =>
(fun, outerArgss)
case _ =>
- error(fun.pos, "unexpected tree in annotationn: "+ fun)
+ error(fun.pos, "unexpected tree in annotation: "+ fun)
(setError(fun), outerArgss)
}
extract(ann, List())
@@ -2661,7 +2717,7 @@ trait Typers { self: Analyzer =>
error(arg.pos, "unknown annotation argument name: " + name)
(nme.ERROR, None)
} else if (!names.contains(sym)) {
- error(arg.pos, "duplicate value for anontation argument " + name)
+ error(arg.pos, "duplicate value for annotation argument " + name)
(nme.ERROR, None)
} else {
names -= sym
@@ -2676,7 +2732,7 @@ trait Typers { self: Analyzer =>
for (name <- names) {
if (!name.annotations.contains(AnnotationInfo(AnnotationDefaultAttr.tpe, List(), List())) &&
!name.hasFlag(DEFAULTPARAM))
- error(ann.pos, "annotation " + annType.typeSymbol.fullNameString + " is missing argument " + name.name)
+ error(ann.pos, "annotation " + annType.typeSymbol.fullName + " is missing argument " + name.name)
}
if (hasError) annotationError
@@ -2959,7 +3015,7 @@ trait Typers { self: Analyzer =>
*/
protected def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
//Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")")
- def ptOrLub(tps: List[Type]) = if (isFullyDefined(pt)) pt else weakLub(tps map (_.deconst))
+ def ptOrLub(tps: List[Type]) = if (isFullyDefined(pt)) (pt, false) else weakLub(tps map (_.deconst))
//@M! get the type of the qualifier in a Select tree, otherwise: NoType
def prefixType(fun: Tree): Type = fun match {
@@ -3024,7 +3080,7 @@ trait Typers { self: Analyzer =>
} else {
// An annotated term, created with annotation ascription
// term : @annot()
- def annotTypeTree(ainfo: AnnotationInfo): Tree =
+ def annotTypeTree(ainfo: AnnotationInfo): Tree = //TR: function not used ??
TypeTree(arg1.tpe.withAnnotation(ainfo)) setOriginal tree
if (ann.tpe == null) {
@@ -3046,7 +3102,7 @@ trait Typers { self: Analyzer =>
context.owner.newAliasType(tree.pos, name) setInfo pt
else
context.owner.newAbstractType(tree.pos, name) setInfo
- mkTypeBounds(NothingClass.tpe, AnyClass.tpe)
+ TypeBounds(NothingClass.tpe, AnyClass.tpe)
val rawInfo = vble.rawInfo
vble = if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
else namer.enterInScope(vble)
@@ -3071,7 +3127,7 @@ trait Typers { self: Analyzer =>
trackSetInfo(vble)(
if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
else body1.tpe)
- treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // buraq, was: pt
+ treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // burak, was: pt
}
}
@@ -3085,14 +3141,9 @@ trait Typers { self: Analyzer =>
}
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
- def mayBeVarGetter(sym: Symbol) = sym.info match {
- case PolyType(List(), _) => sym.owner.isClass && !sym.isStable
- case _: ImplicitMethodType => sym.owner.isClass && !sym.isStable
- case _ => false
- }
val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType)
val varsym = lhs1.symbol
- if ((varsym ne null) && mayBeVarGetter(varsym))
+ if ((varsym ne null) && treeInfo.mayBeVarGetter(varsym))
lhs1 match {
case Select(qual, name) =>
return typed(
@@ -3105,7 +3156,7 @@ trait Typers { self: Analyzer =>
}
if ((varsym ne null) && (varsym.isVariable || varsym.isValue && phase.erasedTypes)) {
- val rhs1 = typed(rhs, lhs1.tpe)
+ val rhs1 = typed(rhs, EXPRmode | BYVALmode, lhs1.tpe)
treeCopy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
} else {
if (!lhs1.tpe.isError) {
@@ -3119,15 +3170,15 @@ trait Typers { self: Analyzer =>
}
def typedIf(cond: Tree, thenp: Tree, elsep: Tree) = {
- val cond1 = checkDead(typed(cond, BooleanClass.tpe))
- if (elsep.isEmpty) { // in the future, should be unecessary
+ val cond1 = checkDead(typed(cond, EXPRmode | BYVALmode, BooleanClass.tpe))
+ if (elsep.isEmpty) { // in the future, should be unnecessary
val thenp1 = typed(thenp, UnitClass.tpe)
treeCopy.If(tree, cond1, thenp1, elsep) setType thenp1.tpe
} else {
var thenp1 = typed(thenp, pt)
var elsep1 = typed(elsep, pt)
- val owntype = ptOrLub(List(thenp1.tpe, elsep1.tpe))
- if (isNumericValueType(owntype)) {
+ val (owntype, needAdapt) = ptOrLub(List(thenp1.tpe, elsep1.tpe))
+ if (needAdapt) { //isNumericValueType(owntype)) {
thenp1 = adapt(thenp1, mode, owntype)
elsep1 = adapt(elsep1, mode, owntype)
}
@@ -3150,7 +3201,7 @@ trait Typers { self: Analyzer =>
" has return statement; needs result type")
} else {
context.enclMethod.returnsSeen = true
- val expr1: Tree = typed(expr, restpt0.tpe)
+ val expr1: Tree = typed(expr, EXPRmode | BYVALmode, restpt0.tpe)
treeCopy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType NothingClass.tpe
}
}
@@ -3273,7 +3324,7 @@ trait Typers { self: Analyzer =>
case _ => false
}
}
- if (errorInResult(fun) || (args exists errorInResult)) {
+ if (errorInResult(fun) || (args exists errorInResult) || errorInResult(tree)) {
if (printTypings) println("second try for: "+fun+" and "+args)
val Select(qual, name) = fun
val args1 = tryTypedArgs(args, argMode(fun, mode), ex)
@@ -3305,10 +3356,14 @@ trait Typers { self: Analyzer =>
case fun1: Tree =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
incCounter(typedApplyCount)
+ def isImplicitMethod(tpe: Type) = tpe match {
+ case mt: MethodType => mt.isImplicit
+ case _ => false
+ }
val res =
if (phase.id <= currentRun.typerPhase.id &&
fun2.isInstanceOf[Select] &&
- !fun2.tpe.isInstanceOf[ImplicitMethodType] &&
+ !isImplicitMethod(fun2.tpe) &&
((fun2.symbol eq null) || !fun2.symbol.isConstructor) &&
(mode & (EXPRmode | SNDTRYmode)) == EXPRmode) {
tryTypedApply(fun2, args)
@@ -3325,7 +3380,7 @@ trait Typers { self: Analyzer =>
// this check is needed to avoid infinite recursion in Duplicators
// (calling typed1 more than once for the same tree)
if (checked ne res) typed { atPos(tree.pos)(checked) }
- else res
+ else res
} else res
/* Would like to do the following instead, but curiously this fails; todo: investigate
if (fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass)
@@ -3439,7 +3494,7 @@ trait Typers { self: Analyzer =>
} else {
findMixinSuper(clazz.info)
}
- tree setSymbol clazz setType mkSuperType(clazz.thisType, owntype)
+ tree setSymbol clazz setType SuperType(clazz.thisType, owntype)
}
}
@@ -3482,36 +3537,40 @@ trait Typers { self: Analyzer =>
val qual1 = adaptToName(qual, name)
if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
+
if (!reallyExists(sym)) {
+ if (context.owner.toplevelClass.hasFlag(JAVA) && name.isTypeName) {
+ val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
+ if (tree1 != EmptyTree) return typed1(tree1, mode, pt)
+ }
+
if (settings.debug.value) Console.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+"\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner)
+
+ def makeErrorTree = {
+ val tree1 = tree match {
+ case Select(_, _) => treeCopy.Select(tree, qual, name)
+ case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
+ }
+ setError(tree1)
+ }
+
+ if (name == nme.ERROR && onlyPresentation)
+ return makeErrorTree
+
if (!qual.tpe.widen.isErroneous) {
error(tree.pos,
if (name == nme.CONSTRUCTOR)
qual.tpe.widen+" does not have a constructor"
else
decode(name)+" is not a member of "+
- (if (qual.tpe.typeSymbol.isTypeParameterOrSkolem) "type parameter " else "") +
- qual.tpe.widen +
+ (if (qual.tpe.typeSymbol.isTypeParameterOrSkolem) "type parameter " else "") +
+ qual.tpe.widen +
(if ((context.unit ne null) && // Martin: why is this condition needed?
qual.pos.isDefined && tree.pos.isDefined && qual.pos.line < tree.pos.line)
"\npossible cause: maybe a semicolon is missing before `"+decode(name)+"'?"
else ""))
}
-
- // Temporary workaround to retain type information for qual so that askTypeCompletion has something to
- // work with. This appears to work in the context of the IDE, but is incorrect and needs to be
- // revisited.
- if (onlyPresentation) {
- // Nb. this appears to throw away the effects of setError, but some appear to be
- // retained across the copy.
- setError(tree)
- val tree1 = tree match {
- case Select(_, _) => treeCopy.Select(tree, qual, name)
- case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
- }
- tree1
- } else
- setError(tree)
+ if (onlyPresentation) makeErrorTree else setError(tree)
} else {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
@@ -3547,7 +3606,7 @@ trait Typers { self: Analyzer =>
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
- var qual: Tree = EmptyTree // the qualififier tree if transformed tree is a select
+ var qual: Tree = EmptyTree // the qualifier tree if transformed tree is a select
// A symbol qualifies if it exists and is not stale. Stale symbols
// are made to disappear here. In addition,
@@ -3570,6 +3629,7 @@ trait Typers { self: Analyzer =>
}
while (defSym == NoSymbol && cx != NoContext) {
+ currentRun.compileSourceFor(context.asInstanceOf[analyzer.Context], name)
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
if ((defEntry ne null) && qualifies(defEntry.sym)) {
@@ -3599,7 +3659,7 @@ trait Typers { self: Analyzer =>
if (defSym.exists && impSym.exists) {
// imported symbols take precedence over package-owned symbols in different
- // compilation units. Defined symbols take precedence over errenous imports.
+ // compilation units. Defined symbols take precedence over erroneous imports.
if (defSym.definedInPackage &&
(!currentRun.compiles(defSym) ||
(context.unit ne null) && defSym.sourceFile != context.unit.source.file))
@@ -3698,7 +3758,7 @@ trait Typers { self: Analyzer =>
//@M! the polytype denotes the expected kind
}
val argtypes = args1 map (_.tpe)
- val owntype = if (tpt1.symbol.isClass || tpt1.symbol.isTypeMember)
+ val owntype = if (tpt1.symbol.isClass || tpt1.symbol.isNonClassType)
// @M! added the latter condition
appliedType(tpt1.tpe, argtypes)
else tpt1.tpe.instantiateTypeParams(tparams, argtypes)
@@ -3734,6 +3794,8 @@ trait Typers { self: Analyzer =>
case PackageDef(pid, stats) =>
val pid1 = typedQualifier(pid).asInstanceOf[RefTree]
assert(sym.moduleClass ne NoSymbol, sym)
+ // complete lazy annotations
+ val annots = sym.annotations
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(stats, NoSymbol)
treeCopy.PackageDef(tree, pid1, stats1) setType NoType
@@ -3826,10 +3888,10 @@ trait Typers { self: Analyzer =>
val body = treeCopy.Match(tree, selector1, cases)
typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
} else {
- val selector1 = checkDead(typed(selector))
+ val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
var cases1 = typedCases(tree, cases, selector1.tpe.widen, pt)
- val owntype = ptOrLub(cases1 map (_.tpe))
- if (isNumericValueType(owntype)) {
+ val (owntype, needAdapt) = ptOrLub(cases1 map (_.tpe))
+ if (needAdapt) {
cases1 = cases1 map (adaptCase(_, owntype))
}
treeCopy.Match(tree, selector1, cases1) setType owntype
@@ -3843,15 +3905,15 @@ trait Typers { self: Analyzer =>
var catches1 = typedCases(tree, catches, ThrowableClass.tpe, pt)
val finalizer1 = if (finalizer.isEmpty) finalizer
else typed(finalizer, UnitClass.tpe)
- val owntype = ptOrLub(block1.tpe :: (catches1 map (_.tpe)))
- if (isNumericValueType(owntype)) {
+ val (owntype, needAdapt) = ptOrLub(block1.tpe :: (catches1 map (_.tpe)))
+ if (needAdapt) {
block1 = adapt(block1, mode, owntype)
catches1 = catches1 map (adaptCase(_, owntype))
}
treeCopy.Try(tree, block1, catches1, finalizer1) setType owntype
case Throw(expr) =>
- val expr1 = typed(expr, ThrowableClass.tpe)
+ val expr1 = typed(expr, EXPRmode | BYVALmode, ThrowableClass.tpe)
treeCopy.Throw(tree, expr1) setType NothingClass.tpe
case New(tpt: Tree) =>
@@ -3943,7 +4005,7 @@ trait Typers { self: Analyzer =>
error(tree.pos, "cannot create a generic multi-dimensional array of more than "+MaxArrayDims+" dimensions")
val newArrayApp = atPos(tree.pos) {
val manif = getManifestTree(tree.pos, manifType, false)
- Apply(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
+ new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
}
typed(newArrayApp, mode, pt)
case tree1 =>
@@ -4007,7 +4069,7 @@ trait Typers { self: Analyzer =>
case Literal(value) =>
tree setType (
if (value.tag == UnitTag) UnitClass.tpe
- else mkConstantType(value))
+ else ConstantType(value))
case SingletonTypeTree(ref) =>
val ref1 = checkStable(
@@ -4028,7 +4090,7 @@ trait Typers { self: Analyzer =>
case TypeBoundsTree(lo, hi) =>
val lo1 = typedType(lo, mode)
val hi1 = typedType(hi, mode)
- treeCopy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
+ treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt, mode)
@@ -4045,7 +4107,7 @@ trait Typers { self: Analyzer =>
assert(onlyPresentation) // should not happen in normal circumstances.
tree setType tree.symbol.tpe
case _ =>
- throw new Error("unexpected tree: " + tree.getClass + "\n" + tree)//debug
+ abort("unexpected tree: " + tree.getClass + "\n" + tree)//debug
}
}
@@ -4096,7 +4158,6 @@ trait Typers { self: Analyzer =>
if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, result)
result
} catch {
- case ex: ControlException => throw ex
case ex: TypeError =>
tree.tpe = null
if (printTypings) println("caught "+ex+" in typed: "+tree);//DEBUG
@@ -4108,13 +4169,9 @@ trait Typers { self: Analyzer =>
if ((context ne null) && (context.unit ne null) &&
(context.unit.source ne null) && (tree ne null))
logError("AT: " + (tree.pos).dbgString, ex);
- throw(ex)
-/*
- case ex: java.lang.Error =>
- Console.println("exception when typing "+tree+", pt = "+pt)
throw ex
-*/ //debug
- } finally {
+ }
+ finally {
if (Statistics.enabled) {
val t = currentTime()
microsByType(pendingTreeTypes.head) += ((t - typerTime) / 1000).toInt
@@ -4154,14 +4211,17 @@ trait Typers { self: Analyzer =>
/** Types qualifier <code>tree</code> of a select node.
* E.g. is tree occurs in a context like <code>tree.m</code>.
- *
- * @param tree ...
- * @return ...
+ */
+ def typedQualifier(tree: Tree, mode: Int, pt: Type): Tree =
+ typed(tree, EXPRmode | QUALmode | POLYmode | mode & TYPEPATmode, pt) // TR: don't set BYVALmode, since qualifier might end up as by-name param to an implicit
+
+ /** Types qualifier <code>tree</code> of a select node.
+ * E.g. is tree occurs in a context like <code>tree.m</code>.
*/
def typedQualifier(tree: Tree, mode: Int): Tree =
- typed(tree, EXPRmode | QUALmode | POLYmode | mode & TYPEPATmode, WildcardType)
+ typedQualifier(tree, mode, WildcardType)
- def typedQualifier(tree: Tree): Tree = typedQualifier(tree, NOmode)
+ def typedQualifier(tree: Tree): Tree = typedQualifier(tree, NOmode, WildcardType)
/** Types function part of an application */
def typedOperator(tree: Tree): Tree =
@@ -4169,20 +4229,13 @@ trait Typers { self: Analyzer =>
/** Types a pattern with prototype <code>pt</code> */
def typedPattern(tree: Tree, pt: Type): Tree = {
- // The commented out code stems from investigation into whether
- // "abc" match { case Seq('a', 'b', 'c') => true }
- // can be ruled out statically. At present this is a runtime
- // error both because there is an implicit from String to Seq
- // (even though such implicits are not used by the matcher) and
- // because the typer is fine with concluding that "abc" might
- // be of type "String with Seq[T]" and thus eligible for a call
- // to unapplySeq.
- //
- // val savedImplicitsEnabled = context.implicitsEnabled
- // context.implicitsEnabled = false
- // try
- typed(tree, PATTERNmode, pt)
- // finally context.implicitsEnabled = savedImplicitsEnabled
+ // We disable implicits because otherwise some constructs will
+ // type check which should not. The pattern matcher does not
+ // perform implicit conversions in an attempt to consummate a match.
+ val savedImplicitsEnabled = context.implicitsEnabled
+ context.implicitsEnabled = false
+ try typed(tree, PATTERNmode, pt)
+ finally context.implicitsEnabled = savedImplicitsEnabled
}
/** Types a (fully parameterized) type tree */
@@ -4235,9 +4288,9 @@ trait Typers { self: Analyzer =>
packedType(tree1, context.owner)
}
- def transformedOrTyped(tree: Tree, pt: Type): Tree = transformed.get(tree) match {
+ def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match {
case Some(tree1) => transformed -= tree; tree1
- case None => typed(tree, pt)
+ case None => typed(tree, mode, pt)
}
def findManifest(tp: Type, full: Boolean) = atPhase(currentRun.typerPhase) {