diff options
Diffstat (limited to 'src/compiler')
18 files changed, 302 insertions, 269 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 89183b99c7..907e8e30ff 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -263,16 +263,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Create a new getter for current symbol (which must be a field) */ - final def newGetter: Symbol = { - val getter = owner.newMethod(focusPos(pos), nme.getterName(name)).setFlag(getterFlags(flags)) - getter.privateWithin = privateWithin - getter.setInfo(MethodType(List(), tpe)) - } + final def newGetter: Symbol = ( + owner.newMethod(focusPos(pos), nme.getterName(name)) + setFlag getterFlags(flags) + setPrivateWithin privateWithin + setInfo MethodType(Nil, tpe) + ) final def newErrorClass(name: TypeName) = { - val clazz = newClass(pos, name).setFlag(SYNTHETIC | IS_ERROR) - clazz.setInfo(ClassInfoType(List(), new ErrorScope(this), clazz)) - clazz + val clazz = newClass(pos, name) + ( clazz + setFlag (SYNTHETIC | IS_ERROR) + setInfo ClassInfoType(Nil, new ErrorScope(this), clazz) + ) } final def newErrorSymbol(name: Name): Symbol = name match { @@ -859,6 +862,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _privateWithin: Symbol = _ def privateWithin = _privateWithin def privateWithin_=(sym: Symbol) { _privateWithin = sym } + def setPrivateWithin(sym: Symbol): this.type = { privateWithin_=(sym) ; this } /** Does symbol have a private or protected qualifier set? */ final def hasAccessBoundary = (privateWithin != null) && (privateWithin != NoSymbol) @@ -930,9 +934,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** Set initial info. */ - def setInfo(info: Type): this.type = { info_=(info); this } - - def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info.atOwner(this)) + def setInfo(info: Type): this.type = { info_=(info); this } + /** Modifies this symbol's info in place. */ + def modifyInfo(f: Type => Type): this.type = setInfo(f(info)) + /** Substitute second list of symbols for first in current info. */ + def substInfo(syms0: List[Symbol], syms1: List[Symbol]) = modifyInfo(_.substSym(syms0, syms1)) + def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info atOwner this) /** Set new info valid from start of this phase. */ final def updateInfo(info: Type): Symbol = { @@ -1123,7 +1130,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => val oldsyms = oldsymbuf.toList val newsyms = newsymbuf.toList for (sym <- newsyms) { - addMember(thistp, tp, sym.setInfo(sym.info.substThis(this, thistp).substSym(oldsyms, newsyms))) + addMember(thistp, tp, sym modifyInfo (_ substThisAndSym(this, thistp, oldsyms, newsyms))) } tp } @@ -1134,11 +1141,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def existentialBound: Type = if (this.isClass) - polyType(this.typeParams, TypeBounds.upper(this.classBound)) + polyType(this.typeParams, TypeBounds.upper(this.classBound)) else if (this.isAbstractType) - this.info + this.info else if (this.isTerm) - TypeBounds.upper(intersectionType(List(this.tpe, SingletonClass.tpe))) + singletonBounds(this.tpe) else abort("unexpected alias type: "+this) @@ -1286,9 +1293,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A clone of this symbol, but with given owner. */ final def cloneSymbol(owner: Symbol): Symbol = { val newSym = cloneSymbolImpl(owner) - newSym.privateWithin = privateWithin - newSym.setInfo(info.cloneInfo(newSym)) - .setFlag(this.rawflags).setAnnotations(this.annotations) + ( newSym + setPrivateWithin privateWithin + setInfo (info cloneInfo newSym) + setFlag this.rawflags + setAnnotations this.annotations + ) } /** Internal method to clone a symbol's implementation without flags or type. */ @@ -2234,7 +2244,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def cloneSymbolImpl(owner: Symbol): Symbol = - new TypeSymbol(owner, pos, name) //.toTypeName) + new TypeSymbol(owner, pos, name) incCounter(typeSymbolCount) } @@ -2442,16 +2452,80 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def originalEnclosingMethod = this } - private def cloneAndSubstInfos[T <: Symbol](syms: List[T])(f: T => Symbol): List[T] = { - val syms1 = syms map (s => f(s).asInstanceOf[T]) - syms1 map (sym1 => sym1 setInfo sym1.info.substSym(syms, syms1)) + /** Derives a new list of symbols from the given list by mapping the given + * list across the given function. Then fixes the info of all the new symbols + * by substituting the new symbols for the original symbols. + * + * @param syms the prototypical symbols + * @param symFn the function to create new symbols + * @return the new list of info-adjusted symbols + */ + def deriveSymbols(syms: List[Symbol], symFn: Symbol => Symbol): List[Symbol] = { + val syms1 = syms map symFn + syms1 map (_ substInfo (syms, syms1)) + } + + /** Derives a new Type by first deriving new symbols as in deriveSymbols, + * then performing the same oldSyms => newSyms substitution on `tpe` as is + * performed on the symbol infos in deriveSymbols. + * + * @param syms the prototypical symbols + * @param symFn the function to create new symbols + * @param tpe the prototypical type + * @return the new symbol-subsituted type + */ + def deriveType(syms: List[Symbol], symFn: Symbol => Symbol)(tpe: Type): Type = { + val syms1 = deriveSymbols(syms, symFn) + tpe.substSym(syms, syms1) + } + /** Derives a new Type by instantiating the given list of symbols as + * WildcardTypes. + * + * @param syms the symbols to replace + * @return the new type with WildcardType replacing those syms + */ + def deriveTypeWithWildcards(syms: List[Symbol])(tpe: Type): Type = { + if (syms.isEmpty) tpe + else tpe.instantiateTypeParams(syms, syms map (_ => WildcardType)) } + /** Convenience functions which derive symbols by cloning. + */ + def cloneSymbols(syms: List[Symbol]): List[Symbol] = + deriveSymbols(syms, _.cloneSymbol) + def cloneSymbolsAtOwner(syms: List[Symbol], owner: Symbol): List[Symbol] = + deriveSymbols(syms, _ cloneSymbol owner) + + /** Clone symbols and apply the given function to each new symbol's info. + * + * @param syms the prototypical symbols + * @param infoFn the function to apply to the infos + * @return the newly created, info-adjusted symbols + */ + def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] = + cloneSymbols(syms) map (_ modifyInfo infoFn) - def cloneSymbols[T <: Symbol](syms: List[T]): List[T] = - cloneAndSubstInfos(syms)(_.cloneSymbol) + /** Functions which perform the standard clone/substituting on the given symbols and type, + * then call the creator function with the new symbols and type as arguments. + */ + def createFromClonedSymbols[T](syms: List[Symbol], tpe: Type)(creator: (List[Symbol], Type) => T): T = { + val syms1 = cloneSymbols(syms) + creator(syms1, tpe.substSym(syms, syms1)) + } + def createFromClonedSymbolsAtOwner[T](syms: List[Symbol], owner: Symbol, tpe: Type)(creator: (List[Symbol], Type) => T): T = { + val syms1 = cloneSymbolsAtOwner(syms, owner) + creator(syms1, tpe.substSym(syms, syms1)) + } - def cloneSymbols[T <: Symbol](syms: List[T], owner: Symbol): List[T] = - cloneAndSubstInfos(syms)(_ cloneSymbol owner) + /** Create a new existential type skolem with the given owner and origin. + */ + def newExistentialSkolem(sym: Symbol, owner: Symbol, origin: AnyRef): TypeSkolem = { + val skolem = new TypeSkolem(owner, sym.pos, sym.name.toTypeName, origin) + ( skolem + setInfo (sym.info cloneInfo skolem) + setFlag (sym.flags | EXISTENTIAL) + resetFlag PARAM + ) + } /** An exception for cyclic references of symbol definitions */ case class CyclicReference(sym: Symbol, info: Type) diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 1ccd668fd6..ff1b759290 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -332,37 +332,26 @@ trait Trees extends api.Trees { self: SymbolTable => override def toString = substituterString("Symbol", "Tree", from, to) } - class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends Traverser { - val typeSubst = new SubstTypeMap(from, to) - def isEmpty = from.isEmpty && to.isEmpty - + class TypeMapTreeSubstituter(val typeMap: TypeMap) extends Traverser { override def traverse(tree: Tree) { - if (tree.tpe ne null) tree.tpe = typeSubst(tree.tpe) - if (tree.isDef) { - val sym = tree.symbol - val info1 = typeSubst(sym.info) - if (info1 ne sym.info) sym.setInfo(info1) - } + if (tree.tpe ne null) + tree.tpe = typeMap(tree.tpe) + if (tree.isDef) + tree.symbol modifyInfo typeMap + super.traverse(tree) } override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) + } + + class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends TypeMapTreeSubstituter(new SubstTypeMap(from, to)) { + def isEmpty = from.isEmpty && to.isEmpty override def toString() = "TreeTypeSubstituter("+from+","+to+")" } lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List()) - class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends Traverser { - val subst = new SubstSymMap(from, to) - override def traverse(tree: Tree) { - if (tree.tpe ne null) tree.tpe = subst(tree.tpe) - if (tree.isDef) { - val sym = tree.symbol - val info1 = subst(sym.info) - if (info1 ne sym.info) sym.setInfo(info1) - } - super.traverse(tree) - } - override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) + class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends TypeMapTreeSubstituter(new SubstSymMap(from, to)) { override def toString() = "TreeSymSubstTraverser/" + substituterString("Symbol", "Symbol", from, to) } diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 7322eec1df..f8255bc846 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -577,11 +577,8 @@ trait Types extends api.Types { self: SymbolTable => val tp1 = existentialAbstraction(m.capturedParams, tp) val result: Type = if (m.capturedSkolems.isEmpty) tp1 - else { - val captured = cloneSymbols(m.capturedSkolems) - captured foreach (_ setFlag CAPTURED) - tp1.substSym(m.capturedSkolems, captured) - } + else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1) + stopTimer(asSeenFromNanos, start) result } @@ -639,9 +636,15 @@ trait Types extends api.Types { self: SymbolTable => */ def substThis(from: Symbol, to: Type): Type = new SubstThisMap(from, to) apply this + def substThis(from: Symbol, to: Symbol): Type = + substThis(from, to.thisType) - def substSuper(from: Type, to: Type): Type = - new SubstSuperMap(from, to) apply this + /** Performs both substThis and substSym in one traversal. + */ + def substThisAndSym(from: Symbol, to: Type, symsFrom: List[Symbol], symsTo: List[Symbol]): Type = { + if (symsFrom eq symsTo) substThis(from, to) + else new SubstThisAndSymMap(from, to, symsFrom, symsTo) apply this + } /** Returns all parts of this type which satisfy predicate `p` */ def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p).collect(this).toList @@ -1122,7 +1125,16 @@ trait Types extends api.Types { self: SymbolTable => // override def isNullable: Boolean = true override def kind = "WildcardType" } - + /** BoundedWildcardTypes, used only during type inference, are created in + * two places that I can find: + * + * 1. If the expected type of an expression is an existential type, + * its hidden symbols are replaced with bounded wildcards. + * 2. When an implicit conversion is being sought based in part on + * the name of a method in the converted type, a HasMethodMatching + * type is created: a MethodType with parameters typed as + * BoundedWildcardTypes. + */ case class BoundedWildcardType(override val bounds: TypeBounds) extends Type { override def isWildcard = true override def safeToString: String = "?" + bounds @@ -1730,7 +1742,6 @@ trait Types extends api.Types { self: SymbolTable => private var normalized: Type = null - override def isStable: Boolean = { sym == NothingClass || sym == SingletonClass || @@ -1861,6 +1872,7 @@ A type's typeSymbol should never be inspected directly. override def typeArgs: List[Type] = args private def typeArgsOrDummies = if (!isHigherKinded) args else dummyArgs // def hasFishyArgs = args == dummyArgs + private def argsMatchTypeParams = sameLength(sym.info.typeParams, args) // @MAT was typeSymbol.unsafeTypeParams, but typeSymbol normalizes now private def typeParamsDirect = @@ -1888,7 +1900,7 @@ A type's typeSymbol should never be inspected directly. // A reference (in a Scala program) to a type that has type // parameters, but where the reference does not include type // arguments. Note that it doesn't matter whether the symbol refers - // to a java or scala symbol, it does matter whether it occurs in + // to a java or scala symbol, but it does matter whether it occurs in // java or scala code. TypeRefs w/o type params that occur in java // signatures/code are considered raw types, and are represented as // existential types. @@ -1896,32 +1908,27 @@ A type's typeSymbol should never be inspected directly. override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type = if (isHigherKinded) { - val substTps = formals.intersect(typeParams) - - if (sameLength(substTps, typeParams)) + if (sameLength(formals intersect typeParams, typeParams)) copyTypeRef(this, pre, sym, actuals) - else if (sameLength(formals, actuals)) // partial application (needed in infer when bunching type arguments from classes and methods together) - copyTypeRef(this, pre, sym, dummyArgs).subst(formals, actuals) - else ErrorType + // partial application (needed in infer when bunching type arguments from classes and methods together) + else + copyTypeRef(this, pre, sym, dummyArgs).instantiateTypeParams(formals, actuals) } else super.instantiateTypeParams(formals, actuals) - - /** @pre: sym.info.typeParams.length == typeArgs.length */ + /** @pre: argsMatchTypeParams */ @inline private def betaReduce: Type = { - if (settings.debug.value) - assert(sym.info.typeParams.length == typeArgs.length, sym.info.typeParams + " and " + typeArgs) // isHKSubType0 introduces synthetic type params so that // betaReduce can first apply sym.info to typeArgs before calling // asSeenFrom. asSeenFrom then skips synthetic type params, which // are used to reduce HO subtyping to first-order subtyping, but // which can't be instantiated from the given prefix and class. transform(sym.info.resultType) - // // this crashes pos/depmet_implicit_tpbetareduce.scala // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner) } + private def isBetaReducible = sym.isAliasType && argsMatchTypeParams // @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala) @inline private def etaExpand: Type = { @@ -1930,22 +1937,16 @@ A type's typeSymbol should never be inspected directly. else typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce? } - override def dealias: Type = - if (sym.isAliasType && sameLength(sym.info.typeParams, args)) { - betaReduce.dealias - } else this + override def dealias = if (isBetaReducible) betaReduce.dealias else this - private def normalize0: Type = + private def normalize0: Type = ( if (pre eq WildcardType) WildcardType // arises when argument-dependent types are approximated (see def depoly in implicits) else if (isHigherKinded) etaExpand // eta-expand, subtyping relies on eta-expansion of higher-kinded types - else if (sym.isAliasType && sameLength(sym.info.typeParams, args)) - betaReduce.normalize // beta-reduce, but don't do partial application -- cycles have been checked in typeRef - else if (sym.isRefinementClass) - sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers - else { - if(sym.isAliasType) ErrorType //println("!!error: "+(pre, sym, sym.info, sym.info.typeParams, args)) - else super.normalize - } + else if (isBetaReducible) betaReduce.normalize // beta-reduce, but don't do partial application -- cycles have been checked in typeRef + else if (sym.isRefinementClass) sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers + else if (sym.isAliasType) ErrorType //println("!!error: "+(pre, sym, sym.info, sym.info.typeParams, args)) + else super.normalize + ) // TODO: test case that is compiled in a specific order and in different runs override def normalize: Type = { @@ -2128,7 +2129,7 @@ A type's typeSymbol should never be inspected directly. override def safeToString = paramString(this) + resultType override def cloneInfo(owner: Symbol) = { - val vparams = cloneSymbols(params, owner) + val vparams = cloneSymbolsAtOwner(params, owner) copyMethodType(this, vparams, resultType.substSym(params, vparams).cloneInfo(owner)) } @@ -2208,7 +2209,7 @@ A type's typeSymbol should never be inspected directly. override def safeToString = typeParamsString(this) + resultType override def cloneInfo(owner: Symbol) = { - val tparams = cloneSymbols(typeParams, owner) + val tparams = cloneSymbolsAtOwner(typeParams, owner) PolyType(tparams, resultType.substSym(typeParams, tparams).cloneInfo(owner)) } @@ -2253,20 +2254,8 @@ A type's typeSymbol should never be inspected directly. override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap override def isHigherKinded = false - override def skolemizeExistential(owner: Symbol, origin: AnyRef) = { - def mkSkolem(tparam: Symbol): Symbol = { - val skolem = new TypeSkolem( - if (owner == NoSymbol) tparam.owner else owner, - tparam.pos, tparam.name.toTypeName, origin) - skolem.setInfo(tparam.info.cloneInfo(skolem)) - .setFlag(tparam.flags | EXISTENTIAL) - .resetFlag(PARAM) - } - val skolems = quantified map mkSkolem - for (skolem <- skolems) - skolem setInfo skolem.info.substSym(quantified, skolems) - underlying.substSym(quantified, skolems) - } + override def skolemizeExistential(owner: Symbol, origin: AnyRef) = + deriveType(quantified, tparam => newExistentialSkolem(tparam, owner orElse tparam.owner, origin))(underlying) private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match { case TypeRef(_, sym, _) :: args1 if (available contains sym) => @@ -2297,10 +2286,8 @@ A type's typeSymbol should never be inspected directly. if (settings.explaintypes.value) "("+str+")" else str } - override def cloneInfo(owner: Symbol) = { - val tparams = cloneSymbols(quantified, owner) - ExistentialType(tparams, underlying.substSym(quantified, tparams)) - } + override def cloneInfo(owner: Symbol) = + createFromClonedSymbolsAtOwner(quantified, owner, underlying)(ExistentialType(_, _)) override def atOwner(owner: Symbol) = if (quantified exists (_.owner != owner)) cloneInfo(owner) else this @@ -2369,6 +2356,16 @@ A type's typeSymbol should never be inspected directly. } } + // Not used yet. + object HasTypeParams { + def unapply(tp: Type): Option[(List[Symbol], Type)] = tp match { + case AnnotatedType(_, tp, _) => unapply(tp) + case ExistentialType(tparams, qtpe) => Some((tparams, qtpe)) + case PolyType(tparams, restpe) => Some((tparams, restpe)) + case _ => None + } + } + //@M // a TypeVar used to be a case class with only an origin and a constr // then, constr became mutable (to support UndoLog, I guess), @@ -2879,7 +2876,8 @@ A type's typeSymbol should never be inspected directly. val syms2 = result.decls.toList val resultThis = result.typeSymbol.thisType for (sym <- syms2) - sym.setInfo(sym.info.substThis(original.typeSymbol, resultThis).substSym(syms1, syms2)) + sym modifyInfo (_ substThisAndSym(original.typeSymbol, resultThis, syms1, syms2)) + result } @@ -3469,7 +3467,7 @@ A type's typeSymbol should never be inspected directly. result ne sym.info } // map is not the identity --> do cloning properly - if (change) cloneSymbols(origSyms) map (s => s setInfo this(s.info)) + if (change) cloneSymbolsAndModify(origSyms, TypeMap.this) // fast path in case nothing changes due to map else origSyms } @@ -3545,8 +3543,7 @@ A type's typeSymbol should never be inspected directly. val eparams = for ((tparam, i) <- tparams.zipWithIndex) yield { clazz.newExistential(clazz.pos, newTypeName("?"+i)).setInfo(tparam.info.bounds) } - for (tparam <- eparams) tparam setInfo tparam.info.substSym(tparams, eparams) - eparams + eparams map (_ substInfo (tparams, eparams)) } // note: it's important to write the two tests in this order, @@ -3769,14 +3766,11 @@ A type's typeSymbol should never be inspected directly. protected def renameBoundSyms(tp: Type): Type = tp match { case MethodType(ps, restp) => - val ps1 = cloneSymbols(ps) - copyMethodType(tp, ps1, renameBoundSyms(restp.substSym(ps, ps1))) + createFromClonedSymbols(ps, restp)((ps1, tp1) => copyMethodType(tp, ps1, renameBoundSyms(tp1))) case PolyType(bs, restp) => - val bs1 = cloneSymbols(bs) - PolyType(bs1, renameBoundSyms(restp.substSym(bs, bs1))) + createFromClonedSymbols(bs, restp)((ps1, tp1) => PolyType(ps1, renameBoundSyms(tp1))) case ExistentialType(bs, restp) => - val bs1 = cloneSymbols(bs) - ExistentialType(bs1, restp.substSym(bs, bs1)) + createFromClonedSymbols(bs, restp)(ExistentialType(_, _)) case _ => tp } @@ -3899,9 +3893,12 @@ A type's typeSymbol should never be inspected directly. case _ => mapOver(tp) } } - - class SubstSuperMap(from: Type, to: Type) extends TypeMap { - def apply(tp: Type): Type = if (tp eq from) to else mapOver(tp) + class SubstThisAndSymMap(fromThis: Symbol, toThis: Type, fromSyms: List[Symbol], toSyms: List[Symbol]) + extends SubstSymMap(fromSyms, toSyms) { + override def apply(tp: Type): Type = tp match { + case ThisType(sym) if sym == fromThis => apply(toThis) + case _ => super.apply(tp) + } } class SubstWildcardMap(from: List[Symbol]) extends TypeMap { @@ -4594,7 +4591,7 @@ A type's typeSymbol should never be inspected directly. sym2 => var e1 = s1.lookupEntry(sym2.name) (e1 ne null) && { - val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType) + val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner) var isEqual = false while (!isEqual && (e1 ne null)) { isEqual = e1.sym.info =:= substSym diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index cac60deaf7..9648befb49 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -88,9 +88,8 @@ trait Erasure { apply(restpe) case mt @ MethodType(params, restpe) => MethodType( - cloneSymbols(params) map (p => p.setInfo(apply(p.tpe))), + cloneSymbolsAndModify(params, ErasureMap.this), if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - // else if (!settings.YdepMethTpes.value) apply(restpe) // this replaces each typeref that refers to an argument // by the type `p.tpe` of the actual argument p (p in params) else apply(mt.resultType(params map (_.tpe)))) @@ -247,7 +246,7 @@ trait Erasure { if (sym.isClassConstructor) tp match { case MethodType(params, TypeRef(pre, sym1, args)) => - MethodType(cloneSymbols(params) map (p => p.setInfo(erasure(sym, p.tpe))), + MethodType(cloneSymbolsAndModify(params, erasure(sym, _)), typeRef(erasure(sym, pre), sym1, args)) } else if (sym.name == nme.apply) diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index b1e4a2a3e0..5297ea6db4 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -64,7 +64,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => * ScalaSignature or ScalaLongSignature annotation. */ def unpickleClass(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = { - def markAbsent(tpe: Type) = List(clazz, module, module.moduleClass) foreach (_ setInfo tpe) + def markAbsent(tpe: Type) = setAllInfos(clazz, module, tpe) def handleError(ex: Exception) = { markAbsent(ErrorType) if (settings.debug.value) ex.printStackTrace() @@ -126,7 +126,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => private class TypeParamCompleter(jtvar: jTypeVariable[_ <: GenericDeclaration]) extends LazyType { override def load(sym: Symbol) = complete(sym) override def complete(sym: Symbol) = { - sym setInfo TypeBounds(NothingClass.tpe, glb(jtvar.getBounds.toList map typeToScala map objToAny)) + sym setInfo TypeBounds.upper(glb(jtvar.getBounds.toList map typeToScala map objToAny)) } } diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala index eaf3c82d5a..35b3a16dc2 100644 --- a/src/compiler/scala/reflect/runtime/Loaders.scala +++ b/src/compiler/scala/reflect/runtime/Loaders.scala @@ -71,12 +71,13 @@ trait Loaders { self: SymbolTable => (clazz, module) } - protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) = { - clazz.setInfo(completer) - module.setInfo(completer) - module.moduleClass.setInfo(completer) + protected def setAllInfos(clazz: Symbol, module: Symbol, info: Type) = { + List(clazz, module, module.moduleClass) foreach (_ setInfo info) } + protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) = + setAllInfos(clazz, module, completer) + /** The type completer for packages. */ class LazyPackageType extends LazyType { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 01b1882481..7dc9b25015 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1230,9 +1230,7 @@ abstract class ClassfileParser { class LazyAliasType(alias: Symbol) extends LazyType { override def complete(sym: Symbol) { - alias.initialize - val tparams1 = cloneSymbols(alias.typeParams) - sym.setInfo(typeFun(tparams1, alias.tpe.substSym(alias.typeParams, tparams1))) + sym setInfo createFromClonedSymbols(alias.initialize.typeParams, alias.tpe)(typeFun) } } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index f364c75a21..00b72bdc1c 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -400,11 +400,12 @@ abstract class Constructors extends Transform with ast.TreeDSL { /** Create a getter or a setter and enter into `clazz` scope */ def addAccessor(sym: Symbol, name: TermName, flags: Long) = { - val m = clazz.newMethod(sym.pos, name) - .setFlag(flags & ~LOCAL & ~PRIVATE) - m.privateWithin = clazz - clazz.info.decls.enter(m) - m + val m = ( + clazz.newMethod(sym.pos, name) + setFlag (flags & ~LOCAL & ~PRIVATE) + setPrivateWithin clazz + ) + clazz.info.decls enter m } def addGetter(sym: Symbol): Symbol = { diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index ad4b1f2429..443a6140dc 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -112,7 +112,7 @@ abstract class LambdaLift extends InfoTransform { // would have the signature // closure: (x$1: Int)() => Int if (sym.isParameter && sym.owner.info.paramss.exists(_ contains sym)) - sym.owner.setInfo(sym.owner.info.cloneInfo(sym.owner)) + sym.owner modifyInfo (_ cloneInfo sym.owner) } changedFreeVars = true debuglog("" + sym + " is free in " + enclosure); diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 0b58e407a6..97f204bc41 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -447,10 +447,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // log("producing type params: " + cloned.map(t => (t, t.tpe.bounds.hi))) for ((orig, cln) <- syms zip cloned) { cln.removeAnnotation(SpecializedClass) - if (env.contains(orig)) cln.setInfo(TypeBounds(cln.info.bounds.lo, AnyRefClass.tpe)) + if (env.contains(orig)) + cln modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe)) } - for (sym <- cloned) sym.setInfo(sym.info.substSym(syms, cloned)) - cloned + cloned map (_ substInfo (syms, cloned)) } /** Maps AnyRef bindings from a raw environment (holding AnyRefs) into type parameters from @@ -510,7 +510,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // log("new tparams " + newClassTParams.zip(newClassTParams map {s => (s.tpe, s.tpe.bounds.hi)}) + ", in env: " + env) def applyContext(tpe: Type) = - subst(env, tpe).subst(survivedParams, newClassTParams map (_.tpe)) + subst(env, tpe).instantiateTypeParams(survivedParams, newClassTParams map (_.tpe)) /** Return a list of specialized parents to be re-mixed in a specialized subclass. * Assuming env = [T -> Int] and @@ -567,8 +567,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { */ def enterMember(sym: Symbol): Symbol = { typeEnv(sym) = fullEnv ++ typeEnv(sym) // append the full environment - sym.setInfo(sym.info.substThis(clazz, ThisType(cls)).subst(oldClassTParams, newClassTParams map (_.tpe))) - + sym modifyInfo (_.substThis(clazz, cls).instantiateTypeParams(oldClassTParams, newClassTParams map (_.tpe))) // we remove any default parameters. At this point, they have been all // resolved by the type checker. Later on, erasure re-typechecks everything and // chokes if it finds default parameters for specialized members, even though @@ -669,7 +668,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { setFlag (OVERRIDE | SPECIALIZED) resetFlag (DEFERRED | CASEACCESSOR | PARAMACCESSOR | LAZY) ) - sym1 setInfo sym1.info.asSeenFrom(clazz.tpe, sym1.owner) + sym1 modifyInfo (_ asSeenFrom (clazz.tpe, sym1.owner)) } val specVal = specializedOverload(cls, m, env) @@ -794,10 +793,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { typeEnv(specMember) = outerEnv ++ env val tps1 = produceTypeParameters(tps, specMember, env) - tps1 foreach (tp => tp.setInfo(tp.info.subst(keys, vals))) + tps1 foreach (_ modifyInfo (_.instantiateTypeParams(keys, vals))) // the cloneInfo is necessary so that method parameter symbols are cloned at the new owner - val methodType = sym.info.resultType.subst(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember) + val methodType = sym.info.resultType.instantiateTypeParams(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember) specMember setInfo polyType(tps1, methodType) debuglog("expanded member: " + sym + ": " + sym.info + @@ -863,9 +862,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { specMember.name = specializedName(sym, env) (specMember - setInfo subst(env, specMember.info.asSeenFrom(owner.thisType, sym.owner)) - setFlag (SPECIALIZED) - resetFlag (DEFERRED | CASEACCESSOR | ACCESSOR | LAZY) + modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner))) + setFlag (SPECIALIZED) + resetFlag (DEFERRED | CASEACCESSOR | ACCESSOR | LAZY) ) } @@ -1056,12 +1055,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { (new FullTypeMap(keys, values))(tpe) } - private def subst(env: TypeEnv)(decl: Symbol): Symbol = { - decl setInfo (subst(env, decl.info) match { - case MethodType(args, _) if decl.isConstructor => MethodType(args, decl.owner.tpe) - case tpe => tpe - }) - } + private def subst(env: TypeEnv)(decl: Symbol): Symbol = + decl modifyInfo (info => + if (decl.isConstructor) MethodType(subst(env, info).params, decl.owner.tpe) + else subst(env, info) + ) /** Checks if the type parameter symbol is not specialized * and is used as type parameters when extending a class with a specialized @@ -1578,7 +1576,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // create fresh symbols for value parameters to hold the skolem types val vparamss1 = List(for (vdef <- vparamss.head; param = vdef.symbol) yield { - ValDef(param.cloneSymbol(symbol).setInfo(param.info.substSym(oldtparams, newtparams))) + ValDef(param cloneSymbol symbol substInfo (oldtparams, newtparams)) }) // replace value and type parameters of the old method with the new ones diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 5013e8f21d..ca16e491e2 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -133,7 +133,7 @@ abstract class TailCalls extends Transform { label setInfo MethodType(thisParam :: method.tpe.params, method.tpe.finalResultType) } if (isEligible) - label setInfo label.tpe.substSym(method.tpe.typeParams, tparams) + label substInfo (method.tpe.typeParams, tparams) } def enclosingType = method.enclClass.typeOfThis diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 45834055a9..c5237b4d59 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -80,6 +80,12 @@ abstract class UnCurry extends InfoTransform private val newMembers = mutable.ArrayBuffer[Tree]() private val repeatedParams = mutable.Map[Symbol, List[ValDef]]() + @inline private def withInPattern[T](value: Boolean)(body: => T): T = { + inPattern = value + try body + finally inPattern = !value + } + private lazy val serialVersionUIDAnnotation = AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List()) @@ -513,9 +519,7 @@ abstract class UnCurry extends InfoTransform } */ case UnApply(fn, args) => - inPattern = false - val fn1 = transform(fn) - inPattern = true + val fn1 = withInPattern(false)(transform(fn)) val args1 = transformTrees(fn.symbol.name match { case nme.unapply => args case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe)) @@ -543,9 +547,7 @@ abstract class UnCurry extends InfoTransform else super.transform(tree) case CaseDef(pat, guard, body) => - inPattern = true - val pat1 = transform(pat) - inPattern = false + val pat1 = withInPattern(true)(transform(pat)) treeCopy.CaseDef(tree, pat1, transform(guard), transform(body)) case fun @ Function(_, _) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 2c32d22081..b67198a292 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -297,8 +297,7 @@ trait Implicits { case _ => tp } def stripped(tp: Type): Type = { - val tparams = freeTypeParametersNoSkolems.collect(tp) - tp.subst(tparams, tparams map (t => WildcardType)) + deriveTypeWithWildcards(freeTypeParametersNoSkolems.collect(tp))(tp) } def sum(xs: List[Int]) = (0 /: xs)(_ + _) def complexity(tp: Type): Int = tp.normalize match { @@ -371,11 +370,7 @@ trait Implicits { /** The type parameters to instantiate */ val undetParams = if (isView) List() else context.outer.undetparams - - def approximate(tp: Type) = - if (undetParams.isEmpty) tp - else tp.instantiateTypeParams(undetParams, undetParams map (_ => WildcardType)) - + def approximate(tp: Type) = deriveTypeWithWildcards(undetParams)(tp) val wildPt = approximate(pt) /** Try to construct a typed tree from given implicit info with given diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index cb548ffdab..68c84b8e15 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -304,25 +304,29 @@ trait Infer { ) } else { - if(sym1.isTerm) + if (sym1.isTerm) sym1.cookJavaRawInfo() // xform java rawtypes into existentials - var owntype = try{ - pre.memberType(sym1) - } catch { - case ex: MalformedType => - if (settings.debug.value) ex.printStackTrace - val sym2 = underlyingSymbol(sym1) - val itype = pre.memberType(sym2) - new AccessError(tree, sym, pre, - "\n because its instance type "+itype+ - (if ("malformed type: "+itype.toString==ex.msg) " is malformed" - else " contains a "+ex.msg)).emit() - ErrorType + val owntype = { + try pre.memberType(sym1) + catch { + case ex: MalformedType => + if (settings.debug.value) ex.printStackTrace + val sym2 = underlyingSymbol(sym1) + val itype = pre.memberType(sym2) + new AccessError(tree, sym, pre, + "\n because its instance type "+itype+ + (if ("malformed type: "+itype.toString==ex.msg) " is malformed" + else " contains a "+ex.msg)).emit() + ErrorType + } + } + tree setSymbol sym1 setType { + pre match { + case _: SuperType => owntype map (tp => if (tp eq pre) site.symbol.thisType else tp) + case _ => owntype + } } - if (pre.isInstanceOf[SuperType]) - owntype = owntype.substSuper(pre, site.symbol.thisType) - tree setSymbol sym1 setType owntype } } @@ -905,8 +909,7 @@ trait Infer { case NullaryMethodType(restpe) => // strip nullary method type, which used to be done by the polytype case below isApplicable(undetparams, restpe, argtpes0, pt) case PolyType(tparams, restpe) => - val tparams1 = cloneSymbols(tparams) - isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes0, pt) + createFromClonedSymbols(tparams, restpe)((tps1, restpe1) => isApplicable(tps1 ::: undetparams, restpe1, argtpes0, pt)) case ErrorType => true case _ => @@ -1278,7 +1281,7 @@ trait Infer { case Nil => Nil case xs => // #3890 - val xs1 = treeSubst.typeSubst mapOver xs + val xs1 = treeSubst.typeMap mapOver xs if (xs ne xs1) new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9e0f70a32c..fe474e5d3d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -130,9 +130,8 @@ trait Namers extends MethodSynthesis { ) def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = { - if (!sym.isPrivateLocal && mods.hasAccessBoundary) - sym.privateWithin = typer.qualifyingClass(tree, mods.privateWithin, true) - sym + if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym + else sym setPrivateWithin typer.qualifyingClass(tree, mods.privateWithin, true) } def setPrivateWithin(tree: MemberDef, sym: Symbol): Symbol = setPrivateWithin(tree, sym, tree.mods) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 1c4355b3bd..66a7f90f0a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1562,14 +1562,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } val existentialParams = new ListBuffer[Symbol] - doTypeTraversal(tree) { // check all bounds, except those that are - // existential type parameters + doTypeTraversal(tree) { // check all bounds, except those that are existential type parameters case ExistentialType(tparams, tpe) => existentialParams ++= tparams case t: TypeRef => - val exparams = existentialParams.toList - val wildcards = exparams map (_ => WildcardType) - checkTypeRef(t.subst(exparams, wildcards), tree.pos) + checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree.pos) case _ => } tree diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index eca33b1aa7..3591732c70 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -54,10 +54,9 @@ trait SyntheticMethods extends ast.TreeDSL { case tp => tp } - def makeMethodPublic(method: Symbol): Symbol = { - method.privateWithin = NoSymbol - method resetFlag AccessFlags - } + def makeMethodPublic(method: Symbol): Symbol = ( + method setPrivateWithin NoSymbol resetFlag AccessFlags + ) def methodArg(method: Symbol, idx: Int): Tree = Ident(method.paramss.head(idx)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index fd75b03297..65eb6466df 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -999,7 +999,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // // val x = expr context.unit.warning(tree.pos, "recovering from existential Skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree) - adapt(tree, mode, pt.subst(pt.existentialSkolems, pt.existentialSkolems map (_ => WildcardType))) + adapt(tree, mode, deriveTypeWithWildcards(pt.existentialSkolems)(pt)) } else throw ex } @@ -1650,7 +1650,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { silent(_.typedTypeConstructor(stringParser(repl).typ())) match { case tpt: Tree => val alias = enclClass.newAliasType(useCase.pos, name.toTypeName) - val tparams = cloneSymbols(tpt.tpe.typeSymbol.typeParams, alias) + val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias) alias setInfo typeFun(tparams, appliedType(tpt.tpe, tparams map (_.tpe))) context.scope.enter(alias) case _ => @@ -1851,23 +1851,23 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def matchesVisibleMember(member: Symbol) = visibleMembers exists { vis => (member.name == vis.name) && - (member.tpe <:< vis.tpe.substThis(vis.owner, ThisType(classDef.symbol))) + (member.tpe <:< vis.tpe.substThis(vis.owner, classDef.symbol)) } // The block is an anonymous class definitions/instantiation pair // -> members that are hidden by the type of the block are made private - ( classDecls filter (member => + val toHide = ( + classDecls filter (member => member.isTerm && member.isPossibleInRefinement && member.isPublic && !matchesVisibleMember(member) + ) map (member => member + resetFlag (PROTECTED | LOCAL) + setFlag (PRIVATE | SYNTHETIC_PRIVATE) + setPrivateWithin NoSymbol ) - foreach { member => - member resetFlag (PROTECTED | LOCAL) - member setFlag (PRIVATE | SYNTHETIC_PRIVATE) - syntheticPrivates += member - member.privateWithin = NoSymbol - } ) + syntheticPrivates ++= toHide case _ => } } @@ -2495,18 +2495,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (args.length > MaxTupleArity) error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity) - def freshArgType(tp: Type): (Type, List[Symbol]) = tp match { + // + def freshArgType(tp: Type): (List[Symbol], Type) = tp match { case MethodType(param :: _, _) => - (param.tpe, Nil) - case PolyType(tparams, restype) => - val tparams1 = cloneSymbols(tparams) - (freshArgType(restype)._1.substSym(tparams, tparams1), tparams1) + (Nil, param.tpe) + case PolyType(tparams, restpe) => + createFromClonedSymbols(tparams, freshArgType(restpe)._2)((ps, t) => ((ps, t))) case OverloadedType(_, _) => error(fun.pos, "cannot resolve overloaded unapply") - (ErrorType, Nil) + (Nil, ErrorType) case _ => error(fun.pos, "an unapply method must accept a single argument.") - (ErrorType, Nil) + (Nil, ErrorType) } val unapp = unapplyMember(otpe) @@ -2516,20 +2516,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (!isApplicableSafe(Nil, unappType, List(pt), WildcardType)) { //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType) - val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree)) - val context1 = context.makeNewScope(context.tree, context.owner) - freeVars foreach context1.scope.enter + val (freeVars, unappFormal) = freshArgType(unappType.skolemizeExistential(context.owner, tree)) + val unapplyContext = context.makeNewScope(context.tree, context.owner) + freeVars foreach unapplyContext.scope.enter - val typer1 = newTyper(context1) + val typer1 = newTyper(unapplyContext) val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe) // turn any unresolved type variables in freevars into existential skolems - val skolems = freeVars map { fv => - val skolem = new TypeSkolem(context1.owner, fun.pos, fv.name.toTypeName, fv) - skolem.setInfo(fv.info.cloneInfo(skolem)) - .setFlag(fv.flags | EXISTENTIAL).resetFlag(PARAM) - skolem - } + val skolems = freeVars map (fv => newExistentialSkolem(fv, unapplyContext.owner, fv)) arg.tpe = pattp.substSym(freeVars, skolems) argDummy setInfo arg.tpe } @@ -2796,7 +2791,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * also replaced, except for term symbols of an Ident tree, where * only the type of the Ident is changed. */ - protected def existentialTransform(rawSyms: List[Symbol], tp: Type) = { + protected def existentialTransform[T](rawSyms: List[Symbol], tp: Type)(creator: (List[Symbol], Type) => T): T = { val typeParams: List[Symbol] = rawSyms map { sym => val name = sym.name match { case x: TypeName => x @@ -2812,28 +2807,19 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // tpeHK for when they are: "if a type constructor is expected/allowed, // tpeHK must be called instead of tpe." val typeParamTypes = typeParams map (_.tpeHK) - ( - typeParams map (tparam => tparam setInfo tparam.info.subst(rawSyms, typeParamTypes)), - tp.subst(rawSyms, typeParamTypes) - ) + def doSubst(info: Type) = info.subst(rawSyms, typeParamTypes) + + creator(typeParams map (_ modifyInfo doSubst), doSubst(tp)) } /** Compute an existential type from raw hidden symbols `syms` and type `tp` */ def packSymbols(hidden: List[Symbol], tp: Type): Type = if (hidden.isEmpty) tp - else { -// Console.println("original type: "+tp) -// Console.println("hidden symbols: "+hidden) - val (tparams, tp1) = existentialTransform(hidden, tp) -// Console.println("tparams: "+tparams+", result: "+tp1) - val res = existentialAbstraction(tparams, tp1) -// Console.println("final result: "+res) - res - } + else existentialTransform(hidden, tp)(existentialAbstraction) def isCapturedExistential(sym: Symbol) = - ((sym hasFlag EXISTENTIAL) && (sym hasFlag CAPTURED)) // todo refine this + sym hasAllFlags (EXISTENTIAL | CAPTURED) // todo refine this def packCaptured(tpe: Type): Type = { val captured = mutable.Set[Symbol]() @@ -2931,12 +2917,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def skolemizeTypeParams(tparams: List[TypeDef]): List[TypeDef] = { class Deskolemizer extends LazyType { override val typeParams = tparams map (_.symbol) - val typeSkolems = typeParams map (_.newTypeSkolem) map (_ setInfo this) - def substitute() = { - // Replace the symbols - (tparams, typeSkolems).zipped foreach (_.symbol = _) - tparams - } + val typeSkolems = typeParams map (_.newTypeSkolem setInfo this) + // Replace the symbols + def substitute() = (tparams, typeSkolems).zipped map (_ setSymbol _) override def complete(sym: Symbol) { // The info of a skolem is the skolemized info of the // actual type parameter of the skolem @@ -2969,9 +2952,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (vd.symbol.tpe.isVolatile) error(vd.pos, "illegal abstraction from value with volatile type "+vd.symbol.tpe) val tpt1 = typedType(tree.tpt, mode) - val (typeParams, tpe) = existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe) - //println(tpe + ": " + tpe.getClass ) - TypeTree(ExistentialType(typeParams, tpe)) setOriginal tree + existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) => + TypeTree(ExistentialType(tparams, tp)) setOriginal tree + ) } // lifted out of typed1 because it's needed in typedImplicit0 @@ -3059,26 +3042,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (!settings.selfInAnnots.value) NoSymbol else - arg1.tpe.selfsym match { - case NoSymbol => - /* Implementation limitation: Currently this - * can cause cyclical reference errors even - * when the self symbol is not referenced at all. - * Surely at least some of these cases can be - * fixed by proper use of LazyType's. Lex tinkered - * on this but did not succeed, so is leaving - * it alone for now. Example code with the problem: - * class peer extends Annotation - * class NPE[T <: NPE[T] @peer] - * - * (Note: -Yself-in-annots must be on to see the problem) - * */ - val sym = - context.owner.newLocalDummy(ann.pos) - .newValue(ann.pos, nme.self) - sym.setInfo(arg1.tpe.withoutAnnotations) - sym - case sym => sym + arg1.tpe.selfsym orElse { + /* Implementation limitation: Currently this + * can cause cyclical reference errors even + * when the self symbol is not referenced at all. + * Surely at least some of these cases can be + * fixed by proper use of LazyType's. Lex tinkered + * on this but did not succeed, so is leaving + * it alone for now. Example code with the problem: + * class peer extends Annotation + * class NPE[T <: NPE[T] @peer] + * + * (Note: -Yself-in-annots must be on to see the problem) + * */ + ( context.owner + newLocalDummy (ann.pos) + newValue (ann.pos, nme.self) + setInfo (arg1.tpe.withoutAnnotations) + ) } val ainfo = typedAnnotation(ann, annotMode, selfsym) |