From 0dde1442dca20cec6142d012b12398d99c1e6b82 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 8 Dec 2008 19:06:16 +0000 Subject: added comments; better errror messages; trace u... added comments; better errror messages; trace utility --- .../scala/tools/nsc/javac/JavaParsers.scala | 2 +- src/compiler/scala/tools/nsc/symtab/Flags.scala | 4 +- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 114 ++++++++++++++++++--- src/compiler/scala/tools/nsc/symtab/Types.scala | 8 +- .../scala/tools/nsc/typechecker/Infer.scala | 8 +- .../scala/tools/nsc/typechecker/RefChecks.scala | 49 ++++++--- .../scala/tools/nsc/typechecker/Typers.scala | 29 +++--- src/compiler/scala/tools/nsc/util/trace.scala | 8 ++ 8 files changed, 172 insertions(+), 50 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/util/trace.scala (limited to 'src/compiler') 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 this.type in this class, * otherwise NoPrefix. + * 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.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 /**

* 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 { * member 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 + } +} -- cgit v1.2.3