summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-12-08 19:06:16 +0000
committerMartin Odersky <odersky@gmail.com>2008-12-08 19:06:16 +0000
commit0dde1442dca20cec6142d012b12398d99c1e6b82 (patch)
tree00cf4270efa5839b9744916ca6dba563b4e2c2dc /src/compiler/scala/tools
parentc8107b0d95890b29ffebe101fc54ce0885511de4 (diff)
downloadscala-0dde1442dca20cec6142d012b12398d99c1e6b82.tar.gz
scala-0dde1442dca20cec6142d012b12398d99c1e6b82.tar.bz2
scala-0dde1442dca20cec6142d012b12398d99c1e6b82.zip
added comments; better errror messages; trace u...
added comments; better errror messages; trace utility
Diffstat (limited to 'src/compiler/scala/tools')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/javac/JavaParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala114
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala29
-rw-r--r--src/compiler/scala/tools/nsc/util/trace.scala8
8 files changed, 172 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index 1e0d20da1b..79b1921ba3 100755
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -398,7 +398,7 @@ trait JavaParsers extends JavaScanners {
in.nextToken
case PROTECTED =>
flags |= Flags.PROTECTED
- privateWithin = thisPackageName
+ //privateWithin = thisPackageName
in.nextToken
case PRIVATE =>
flags |= Flags.PRIVATE
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index c387feefea..4cde113ea2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -42,7 +42,7 @@ object Flags extends Enumeration {
final val INCONSTRUCTOR = 0x00020000 // class symbol is defined in this/superclass
// constructor.
final val ABSOVERRIDE = 0x00040000 // combination of abstract & override
- final val LOCAL = 0x00080000 // symbol is local to current class.
+ final val LOCAL = 0x00080000 // symbol is local to current class (i.e. private[this] or protected[this]
// pre: PRIVATE or PROTECTED are also set
final val JAVA = 0x00100000 // symbol was defined by a Java class
final val SYNTHETIC = 0x00200000 // symbol is compiler-generated
@@ -54,7 +54,7 @@ object Flags extends Enumeration {
final val CASEACCESSOR = 0x01000000 // symbol is a case parameter (or its accessor)
final val TRAIT = 0x02000000 // symbol is a trait
final val BRIDGE = 0x04000000 // function is a bridge method. Set by Erasure
- final val ACCESSOR = 0x08000000 // a value or variable accessor
+ final val ACCESSOR = 0x08000000 // a value or variable accessor (getter or setter)
final val SUPERACCESSOR = 0x10000000 // a super accessor
final val PARAMACCESSOR = 0x20000000 // for value definitions: is an access method
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 5ef82e4db7..a56485313f 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -50,7 +50,9 @@ trait Symbols {
var rawname = initName
var rawflags: Long = 0
private var rawpos = initPos
- val id = { ids += 1; ids }
+
+ val id = { ids += 1; ids } // identity displayed when -uniqid
+
// assert(id != 7498, initName+"/"+initOwner)
var validTo: Period = NoPeriod
@@ -101,6 +103,7 @@ trait Symbols {
}
var privateWithin: Symbol = _
+ // set when symbol has a modifier of the form private[X], NoSymbol otherwise.
// Creators -------------------------------------------------------------------
@@ -110,6 +113,7 @@ trait Symbols {
newValue(pos, name).setFlag(MUTABLE)
final def newValueParameter(pos: Position, name: Name) =
newValue(pos, name).setFlag(PARAM)
+ /** Create local dummy for template (owner of local blocks) */
final def newLocalDummy(pos: Position) =
newValue(pos, nme.LOCAL(this)).setInfo(NoType)
final def newMethod(pos: Position, name: Name) =
@@ -135,11 +139,31 @@ trait Symbols {
newValue(pos, nme.this_).setFlag(SYNTHETIC)
final def newImport(pos: Position) =
newValue(pos, nme.IMPORT)
+
+ /** @param pre type relative to which alternatives are seen.
+ * for instance:
+ * class C[T] {
+ * def m(x: T): T
+ * def m'(): T
+ * }
+ * val v: C[Int]
+ *
+ * Then v.m has symbol TermSymbol(flags = {OVERLOADED},
+ * tpe = OverloadedType(C[Int], List(m, m')))
+ * You recover the type of m doing a
+ *
+ * m.tpe.asSeenFrom(pre, C) (generally, owner of m, which is C here).
+ *
+ * or:
+ *
+ * pre.memberType(m)
+ */
final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
newValue(alternatives.head.pos, alternatives.head.name)
.setFlag(OVERLOADED)
.setInfo(OverloadedType(pre, alternatives))
+ /** for explicit outer phase */
final def newOuterAccessor(pos: Position) = {
val sym = newMethod(pos, nme.OUTER)
sym setFlag (STABLE | SYNTHETIC)
@@ -151,21 +175,40 @@ trait Symbols {
final def newErrorValue(name: Name) =
newValue(pos, name).setFlag(SYNTHETIC | IS_ERROR).setInfo(ErrorType)
+
+ /** Symbol of a type definition type T = ...
+ */
final def newAliasType(pos: Position, name: Name) =
new TypeSymbol(this, pos, name)
+
+ /** Symbol of an abstract type type T >: ... <: ...
+ */
final def newAbstractType(pos: Position, name: Name) =
new TypeSymbol(this, pos, name).setFlag(DEFERRED)
+
+ /** Symbol of a type parameter
+ */
final def newTypeParameter(pos: Position, name: Name) =
newAbstractType(pos, name).setFlag(PARAM)
+
+ /** Type skolems are type parameters ``seen from the inside''
+ * Given a class C[T]
+ * Then the class has a TypeParameter with name `T' in its typeParams list
+ * While type checking the class, there's a local copy of `T' which is a TypeSkolem
+ */
final def newTypeSkolem: Symbol =
new TypeSkolem(owner, pos, name, this)
.setFlag(flags)
+
final def newClass(pos: Position, name: Name) =
new ClassSymbol(this, pos, name)
+
final def newModuleClass(pos: Position, name: Name) =
new ModuleClassSymbol(this, pos, name)
+
final def newAnonymousClass(pos: Position) =
newClass(pos, nme.ANON_CLASS_NAME.toTypeName)
+
final def newAnonymousFunctionClass(pos: Position) = {
val anonfun = newClass(pos, nme.ANON_FUN_NAME.toTypeName)
def firstNonSynOwner(chain: List[Symbol]): Symbol = (chain: @unchecked) match {
@@ -177,13 +220,19 @@ trait Symbols {
AnnotationInfo(definitions.SerializableAttr.tpe, List(), List()) :: anonfun.attributes
anonfun
}
+
+ /** Refinement types P { val x: String; type T <: Number }
+ * also have symbols, they are refinementClasses
+ */
final def newRefinementClass(pos: Position) =
newClass(pos, nme.REFINE_CLASS_NAME.toTypeName)
+
final def newErrorClass(name: Name) = {
val clazz = newClass(pos, name).setFlag(SYNTHETIC | IS_ERROR)
clazz.setInfo(ClassInfoType(List(), new ErrorScope(this), clazz))
clazz
}
+
final def newErrorSymbol(name: Name): Symbol =
if (name.isTypeName) newErrorClass(name) else newErrorValue(name)
@@ -230,23 +279,31 @@ trait Symbols {
def isTerm = false //to be overridden
def isType = false //to be overridden
def isClass = false //to be overridden
- def isTypeMember = false //to be overridden
+ def isTypeMember = false //to be overridden todo: rename, it's something
+ // whose definition starts with `type', i.e. a type
+ // which is not a class.
def isAliasType = false //to be overridden
def isAbstractType = false //to be overridden
def isSkolem = false //to be overridden
+ /** Term symbols with the exception of static parts of Java classes and packages */
final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA))
+
final def isVariable = isTerm && hasFlag(MUTABLE) && !isMethod
+
+ // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
final def isCapturedVariable = isVariable && hasFlag(CAPTURED)
final def isGetter = isTerm && hasFlag(ACCESSOR) && !nme.isSetterName(name)
final def isSetter = isTerm && hasFlag(ACCESSOR) && nme.isSetterName(name)
//todo: make independent of name, as this can be forged.
+
final def hasGetter = isTerm && nme.isLocalName(name)
+
final def isValueParameter = isTerm && hasFlag(PARAM)
final def isLocalDummy = isTerm && nme.isLocalDummyName(name)
final def isMethod = isTerm && hasFlag(METHOD)
- final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD
+ final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD // ???
final def isLabel = isMethod && !hasFlag(ACCESSOR) && hasFlag(LABEL)
final def isInitializedToDefault = !isType && (getFlag(DEFAULTINIT | ACCESSOR) == (DEFAULTINIT | ACCESSOR))
final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR)
@@ -263,10 +320,15 @@ trait Symbols {
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
final def isTypeSkolem = isSkolem && hasFlag(PARAM)
final def isTypeParameter = isTypeParameterOrSkolem && !isSkolem
+ // a type symbol bound by an existential type, for instance the T in
+ // List[T] forSome { type T }
final def isExistential = isType && hasFlag(EXISTENTIAL)
final def isExistentialSkolem = isSkolem && hasFlag(EXISTENTIAL)
final def isExistentialQuantified = isExistential && !isSkolem
+
+ // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
+
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME)
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
def isAnonymousFunction = hasFlag(SYNTHETIC) && (originalName startsWith nme.ANON_FUN_NAME)
@@ -466,6 +528,7 @@ trait Symbols {
def ownerChain: List[Symbol] = this :: owner.ownerChain
+ // same as ownerChain contains sym, but more efficient
def hasTransOwner(sym: Symbol) = {
var o = this
while ((o ne sym) && (o ne NoSymbol)) o = o.owner
@@ -576,13 +639,8 @@ trait Symbols {
def setInfo(info: Type): this.type = {
assert(info ne null)
infos = TypeHistory(currentPeriod, info, null)
- if (info.isComplete) {
- unlock()
- validTo = currentPeriod
- } else {
- unlock()
- validTo = NoPeriod
- }
+ unlock()
+ validTo = if (info.isComplete) currentPeriod else NoPeriod
this
}
@@ -642,6 +700,7 @@ trait Symbols {
infos.info
}
+ // adapt to new run in fsc.
private def adaptInfos(infos: TypeHistory): TypeHistory =
if (infos == null || runId(infos.validFrom) == currentRunId) {
infos
@@ -706,7 +765,11 @@ trait Symbols {
attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz))
/** The least proper supertype of a class; includes all parent types
- * and refinement where needed
+ * and refinement where needed. You need to compute that in a situation like this:
+ * {
+ * class C extends P { ... }
+ * new C
+ * }
*/
def classBound: Type = {
val tp = refinedType(info.parents, owner)
@@ -869,18 +932,19 @@ trait Symbols {
/** If symbol is a class, the type <code>this.type</code> in this class,
* otherwise <code>NoPrefix</code>.
+ * We always have: thisType <:< typeOfThis
*/
def thisType: Type = NoPrefix
/** Return every accessor of a primary constructor parameter in this case class
- */
+ */
final def caseFieldAccessors: List[Symbol] =
info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(CASEACCESSOR))
final def constrParamAccessors: List[Symbol] =
info.decls.toList filter (sym => !sym.isMethod && sym.hasFlag(PARAMACCESSOR))
- /** The symbol accessed by this accessor function.
+ /** The symbol accessed by this accessor (getter or setter) function.
*/
final def accessed: Symbol = {
assert(hasFlag(ACCESSOR))
@@ -900,7 +964,8 @@ trait Symbols {
else owner.outerClass
/** For a paramaccessor: a superclass paramaccessor for which this symbol
- * is an alias, NoSymbol for all others */
+ * is an alias, NoSymbol for all others
+ */
def alias: Symbol = NoSymbol
/** For a lazy value, it's lazy accessor. NoSymbol for all others */
@@ -956,7 +1021,7 @@ trait Symbols {
}
/** The class with the same name in the same package as this module or
- * case class factory
+ * case class factory. A better name would be companionClassOfModule.
*/
final def linkedClassOfModule: Symbol = {
if (this != NoSymbol)
@@ -965,7 +1030,7 @@ trait Symbols {
}
/** The module or case class factory with the same name in the same
- * package as this class.
+ * package as this class. A better name would be companionModuleOfClass.
*/
final def linkedModuleOfClass: Symbol =
if (this.isClass && !this.isAnonymousClass && !this.isRefinementClass) {
@@ -983,6 +1048,12 @@ trait Symbols {
/** For a module class its linked class, for a plain class
* the module class of its linked module.
+ * For instance:
+ * object Foo
+ * class Foo
+ *
+ * Then object Foo has a `moduleClass' (invisible to the user, the backend calls it Foo$
+ * linkedClassOFClass goes from class Foo$ to class Foo, and back.
*/
final def linkedClassOfClass: Symbol =
if (isModuleClass) linkedClassOfModule else linkedModuleOfClass.moduleClass
@@ -1446,6 +1517,15 @@ trait Symbols {
override def isAbstractType = isDeferred
override def isAliasType = !isDeferred
+ /** Let's say you have a type definition
+ *
+ * type T <: Number
+ *
+ * and tsym is the symbol corresponding to T. Then
+ *
+ * tsym.info = TypeBounds(Nothing, Number)
+ * tsym.tpe = TypeRef(NoPrefix, T, List())
+ */
override def tpe: Type = {
if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
if (tpePeriod != currentPeriod) {
@@ -1591,6 +1671,8 @@ trait Symbols {
/** A symbol carrying the self type of the class as its type */
override def thisSym: Symbol = thissym
+ /** the self type of an object foo is foo.type, not class<foo>.this.type
+ */
override def typeOfThis: Type =
if (getFlag(MODULE | IMPLCLASS) == MODULE && owner != NoSymbol)
singleType(owner.thisType, sourceModule)
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 85e19a2b6b..46f4981c97 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1828,6 +1828,8 @@ A type's typeSymbol should never be inspected directly.
/** The variable's skolemizatuon level */
val level = skolemizationLevel
+ override def isHigherKinded = origin.isHigherKinded
+
def setInst(tp: Type) {
// assert(!(tp containsTp this), this)
constr.inst = tp
@@ -2153,6 +2155,7 @@ A type's typeSymbol should never be inspected directly.
case ErrorType => tycon
case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check
+ case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args))
case _ => throw new Error(debugString(tycon))
}
@@ -2302,8 +2305,9 @@ A type's typeSymbol should never be inspected directly.
}
override def toString =
- lobounds.mkString("[ _>:(", ",", ") ") +
- hibounds.mkString("| _<:(", ",", ") ] _= ") + inst
+ (lobounds map (_.safeToString)).mkString("[ _>:(", ",", ") ") +
+ (hibounds map (_.safeToString)).mkString("| _<:(", ",", ") ] _= ") +
+ inst.safeToString
}
/** A prototype for mapping a function over all possible types
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 8d9fed4006..661f225bf3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -772,12 +772,12 @@ trait Infer {
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
- if(!kindErrors.isEmpty)
+ if(!kindErrors.isEmpty) {
error(pos,
- prefix + "the kinds of the type arguments " + targs.mkString("(", ",", ")") +
+ prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
" do not conform to the expected kinds of the type parameters "+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
kindErrors.toList.mkString("\n", ", ", ""))
- else if (!isWithinBounds(pre, owner, tparams, targs)) {
+ } else if (!isWithinBounds(pre, owner, tparams, targs)) {
if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
//val bounds = instantiatedBounds(pre, owner, tparams, targs)//DEBUG
//println("bounds = "+bounds+", targs = "+targs+", targclasses = "+(targs map (_.getClass))+", parents = "+(targs map (_.parents)))
@@ -876,7 +876,7 @@ trait Infer {
}
val errors = new ListBuffer[String]
- (tparams zip targs).foreach{ case (tparam, targ) if(targ.isHigherKinded || !tparam.typeParams.isEmpty) => //println("check: "+(tparam, targ))
+ (tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) => //println("check: "+(tparam, targ))
val (arityMismatches, varianceMismatches, stricterBounds) =
checkKindBoundsHK(targ.typeParams, targ.typeSymbolDirect, tparam, tparam.owner) // NOTE: *not* targ.typeSymbol, which normalizes
// NOTE 2: must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index d1f0edc7c1..486fe6b391 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -10,6 +10,7 @@ import symtab.Flags._
import collection.mutable.{HashSet, HashMap}
import transform.InfoTransform
import scala.tools.nsc.util.{Position, NoPosition}
+import scala.collection.mutable.ListBuffer
/** <p>
* Post-attribution checking and transformation.
@@ -92,6 +93,21 @@ abstract class RefChecks extends InfoTransform {
*/
private def checkAllOverrides(clazz: Symbol) {
+ case class MixinOverrideError(member: Symbol, msg: String)
+
+ var mixinOverrideErrors = new ListBuffer[MixinOverrideError]()
+
+ def printMixinOverrideErrors() {
+ mixinOverrideErrors.toList match {
+ case List() =>
+ case List(MixinOverrideError(_, msg)) =>
+ unit.error(clazz.pos, msg)
+ case MixinOverrideError(member, msg) :: others =>
+ unit.error(clazz.pos, msg+";\n other members with override errors are: "+
+ (others.map(_.member.name).filter(member.name != _).removeDuplicates mkString ", "))
+ }
+ }
+
val self = clazz.thisType
def isAbstractTypeWithoutFBound(sym: Symbol) = // (part of DEVIRTUALIZE)
@@ -130,18 +146,19 @@ abstract class RefChecks extends InfoTransform {
* <code>member</code> are met.
*/
def checkOverride(clazz: Symbol, member: Symbol, other: Symbol) {
- val pos = if (member.owner == clazz) member.pos else clazz.pos
def overrideError(msg: String) {
- if (other.tpe != ErrorType && member.tpe != ErrorType)
- unit.error(pos, "overriding " + infoStringWithLocation(other) +
- ";\n " + infoString(member) + " " + msg +
- (if ((other.owner isSubClass member.owner) &&
- other.isDeferred && !member.isDeferred)
- ";\n (Note that "+infoStringWithLocation(other)+" is abstract,"+
- "\n and is therefore overridden by concrete "+
- infoStringWithLocation(member)+")"
- else ""))
+ if (other.tpe != ErrorType && member.tpe != ErrorType) {
+ val fullmsg =
+ "overriding "+infoStringWithLocation(other)+";\n "+
+ infoString(member)+" "+msg+
+ (if ((other.owner isSubClass member.owner) && other.isDeferred && !member.isDeferred)
+ ";\n (Note that "+infoStringWithLocation(other)+" is abstract,"+
+ "\n and is therefore overridden by concrete "+infoStringWithLocation(member)+")"
+ else "")
+ if (member.owner == clazz) unit.error(member.pos, fullmsg)
+ else mixinOverrideErrors += new MixinOverrideError(member, fullmsg)
+ }
}
def overrideTypeError() {
@@ -198,7 +215,7 @@ abstract class RefChecks extends InfoTransform {
(other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.hasFlag(LAZY)) {
overrideError("cannot override a mutable variable")
} else if (other.isStable && !member.isStable) { // (1.4)
- overrideError("is not stable")
+ overrideError("needs to be a stable, immutable value")
} else if (member.isValue && (member hasFlag LAZY) &&
other.isValue && !other.isSourceMethod && !other.isDeferred && !(other hasFlag LAZY)) {
overrideError("cannot override a concrete non-lazy value")
@@ -219,7 +236,7 @@ abstract class RefChecks extends InfoTransform {
// overrideError("may not be parameterized");
var memberTp = self.memberType(member)
val otherTp = self.memberInfo(other)
- if (!(otherTp.bounds containsType memberTp)) { // (1.7.1) {
+ if (!(otherTp.bounds containsType memberTp)) { // (1.7.1)
overrideTypeError(); // todo: do an explaintypes with bounds here
explainTypes(_.bounds containsType _, otherTp, memberTp)
}
@@ -261,6 +278,8 @@ abstract class RefChecks extends InfoTransform {
opc.next
}
+ printMixinOverrideErrors()
+
// 2. Check that only abstract classes have deferred members
if (clazz.isClass && !clazz.isTrait) {
def abstractClassError(mustBeMixin: Boolean, msg: String) {
@@ -430,10 +449,14 @@ abstract class RefChecks extends InfoTransform {
val v = relativeVariance(sym);
if (v != AnyVariance && sym.variance != v * variance) {
//Console.println("relativeVariance(" + base + "," + sym + ") = " + v);//DEBUG
+ def tpString(tp: Type) = tp match {
+ case ClassInfoType(parents, _, clazz) => "supertype "+intersectionType(parents, clazz.owner)
+ case _ => "type "+tp
+ }
unit.error(base.pos,
varianceString(sym.variance) + " " + sym +
" occurs in " + varianceString(v * variance) +
- " position in type " + base.info + " of " + base);
+ " position in " + tpString(base.info) + " of " + base);
}
}
validateVariance(pre, variance)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 209760a66e..34a7eb5732 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2841,7 +2841,8 @@ trait Typers { self: Analyzer =>
case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name)
}
val result = stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt)
- if (!global.phase.erasedTypes && settings.Xchecknull.value &&
+ if (phase.id <= currentRun.typerPhase.id &&
+ settings.Xchecknull.value &&
!sym.isConstructor &&
!(qual.tpe <:< NotNullClass.tpe) && !qual.tpe.isNotNull)
unit.warning(tree.pos, "potential null pointer dereference: "+tree)
@@ -3336,7 +3337,19 @@ trait Typers { self: Analyzer =>
* @param pt ...
* @return ...
*/
- def typed(tree: Tree, mode: Int, pt: Type): Tree =
+ def typed(tree: Tree, mode: Int, pt: Type): Tree = {
+
+ def dropExistential(tp: Type): Type = tp match {
+ case ExistentialType(tparams, tpe) =>
+ if (settings.debug.value) println("drop ex "+tree+" "+tp)
+ new SubstWildcardMap(tparams).apply(tp)
+ case TypeRef(_, sym, _) if sym.isAliasType =>
+ val tp0 = tp.normalize
+ val tp1 = dropExistential(tp0)
+ if (tp1 eq tp0) tp else tp1
+ case _ => tp
+ }
+
try {
if (settings.debug.value)
assert(pt ne null, tree)//debug
@@ -3346,16 +3359,7 @@ trait Typers { self: Analyzer =>
if (tree.hasSymbol) tree.symbol = NoSymbol
}
if (printTypings) println("typing "+tree+", "+context.undetparams+(mode & TYPEPATmode)); //DEBUG
- def dropExistential(tp: Type): Type = tp match {
- case ExistentialType(tparams, tpe) =>
- if (settings.debug.value) println("drop ex "+tree+" "+tp)
- new SubstWildcardMap(tparams).apply(tp)
- case TypeRef(_, sym, _) if sym.isAliasType =>
- val tp0 = tp.normalize
- val tp1 = dropExistential(tp0)
- if (tp1 eq tp0) tp else tp1
- case _ => tp
- }
+
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt); //DEBUG
@@ -3380,6 +3384,7 @@ trait Typers { self: Analyzer =>
logError("AT: " + (tree.pos).dbgString, ex);
throw(ex)
}
+ }
def atOwner(owner: Symbol): Typer =
newTyper(context.make(context.tree, owner))
diff --git a/src/compiler/scala/tools/nsc/util/trace.scala b/src/compiler/scala/tools/nsc/util/trace.scala
new file mode 100644
index 0000000000..a24a18ec45
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/trace.scala
@@ -0,0 +1,8 @@
+package scala.tools.nsc.util
+
+object trace {
+ def apply[T](msg: String)(value: T): T = {
+ println(msg+value)
+ value
+ }
+}