summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--src/library/scala/collection/mutable/ResizableArray.scala2
-rw-r--r--test/files/neg/tcpoly_variance_enforce.check22
-rw-r--r--test/files/neg/variances.check2
-rw-r--r--test/files/neg/variances.scala12
12 files changed, 197 insertions, 63 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
+ }
+}
diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala
index 211d785a61..19f9e3d6da 100644
--- a/src/library/scala/collection/mutable/ResizableArray.scala
+++ b/src/library/scala/collection/mutable/ResizableArray.scala
@@ -23,7 +23,7 @@ import Predef._
trait ResizableArray[A] extends RandomAccessSeq[A] {
protected def initialSize: Int = 16
- protected var array: Array[AnyRef] = new Array[AnyRef](initialSize)
+ protected var array: Array[AnyRef] = new Array[AnyRef](initialSize min 1)
private var size1: Int = 0
protected def size0: Int = size1
protected def size0_=(sz: Int) { size1 = sz }
diff --git a/test/files/neg/tcpoly_variance_enforce.check b/test/files/neg/tcpoly_variance_enforce.check
index c13a09221f..508ed90fbb 100644
--- a/test/files/neg/tcpoly_variance_enforce.check
+++ b/test/files/neg/tcpoly_variance_enforce.check
@@ -1,44 +1,44 @@
-tcpoly_variance_enforce.scala:15: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+tcpoly_variance_enforce.scala:15: error: kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared covariant
object fcollinv extends coll[FooInvar] // error
^
-tcpoly_variance_enforce.scala:16: error: the kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+tcpoly_variance_enforce.scala:16: error: kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
FooContra's type parameters do not match type m's expected parameters: type x (in class FooContra) is contravariant, but type x is declared covariant
object fcollcon extends coll[FooContra] // error
^
-tcpoly_variance_enforce.scala:17: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+tcpoly_variance_enforce.scala:17: error: kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll.
FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: Nothing <: String are stricter than type x's declared bounds >: Nothing <: Any
object fcollwb extends coll[FooString] // error
^
-tcpoly_variance_enforce.scala:19: error: the kinds of the type arguments (FooCov) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+tcpoly_variance_enforce.scala:19: error: kinds of the type arguments (FooCov) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
FooCov's type parameters do not match type m's expected parameters: type x (in class FooCov) is covariant, but type x is declared contravariant
object fcoll2ok extends coll2[FooCov] // error
^
-tcpoly_variance_enforce.scala:20: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+tcpoly_variance_enforce.scala:20: error: kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared contravariant
object fcoll2inv extends coll2[FooInvar] // error
^
-tcpoly_variance_enforce.scala:22: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
+tcpoly_variance_enforce.scala:22: error: kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
FooString's type parameters do not match type m's expected parameters: type x (in class FooString) is covariant, but type x is declared contravarianttype x (in class FooString)'s bounds >: Nothing <: String are stricter than type x's declared bounds >: Nothing <: Any
object fcoll2wb extends coll2[FooString] // error
^
-tcpoly_variance_enforce.scala:27: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll3.
+tcpoly_variance_enforce.scala:27: error: kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll3.
FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: Nothing <: String are stricter than type x's declared bounds >: Nothing <: Any
object fcoll3wb extends coll3[FooString] // error
^
-tcpoly_variance_enforce.scala:30: error: the kinds of the type arguments (FooString,Int) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
+tcpoly_variance_enforce.scala:30: error: kinds of the type arguments (FooString,Int) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: Nothing <: String are stricter than type x's declared bounds >: Nothing <: y
object fcoll4_1 extends coll4[FooString, Int] // error
^
-tcpoly_variance_enforce.scala:31: error: the kinds of the type arguments (FooString,Any) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
+tcpoly_variance_enforce.scala:31: error: kinds of the type arguments (FooString,Any) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: Nothing <: String are stricter than type x's declared bounds >: Nothing <: y
object fcoll4_2 extends coll4[FooString, Any] // error
^
-tcpoly_variance_enforce.scala:37: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+tcpoly_variance_enforce.scala:37: error: kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.
FooInvar's type parameters do not match type m's expected parameters: type x (in class FooInvar) is invariant, but type x is declared covariant
def x: coll[FooInvar] = error("foo") // error
^
-tcpoly_variance_enforce.scala:38: error: the kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
+tcpoly_variance_enforce.scala:38: error: kinds of the type arguments (FooContra) do not conform to the expected kinds of the type parameters (type m) in trait coll.
FooContra's type parameters do not match type m's expected parameters: type x (in class FooContra) is contravariant, but type x is declared covariant
def y: coll[FooContra] = error("foo") // error
^
diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check
index d809d0f598..5c8ddd5159 100644
--- a/test/files/neg/variances.check
+++ b/test/files/neg/variances.check
@@ -4,7 +4,7 @@ variances.scala:4: error: covariant type A occurs in contravariant position in t
variances.scala:14: error: covariant type A occurs in contravariant position in type A of value a
private[this] def setA(a : A) = this.a = a
^
-variances.scala:16: error: covariant type A occurs in invariant position in type test.C[A] with ScalaObject{def this(): object Foo.this.Baz} of object Baz
+variances.scala:16: error: covariant type A occurs in invariant position in supertype test.C[A] with ScalaObject of object Baz
object Baz extends C[A]
^
three errors found
diff --git a/test/files/neg/variances.scala b/test/files/neg/variances.scala
index 393a3e0b7d..67783bc4aa 100644
--- a/test/files/neg/variances.scala
+++ b/test/files/neg/variances.scala
@@ -58,4 +58,16 @@ object Covariant {
val x : java.lang.Character = test.a.getA
Console.println("XXX " + x)
}
+
+ abstract class T[+A] {
+ val x: T[A] {
+ val m: A => A
+ }
+ }
+ object ST extends T[String] {
+ val x: T[String] { val m: String => String } = ST
+ val m: String => String = (_.substring(1))
+ }
+ val t: T[Any] = ST
+ t.x.m(new Object)
}