summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-11-19 06:59:19 +0000
committerPaul Phillips <paulp@improving.org>2011-11-19 06:59:19 +0000
commit334872e33be8385678697f3d670c8102d38cdca7 (patch)
treed89531734d6c57e0dcd2eb7bd934e8beae888633
parent7eb6f102e8e3bf90319e0339938d7e6eb5aaea43 (diff)
downloadscala-334872e33be8385678697f3d670c8102d38cdca7.tar.gz
scala-334872e33be8385678697f3d670c8102d38cdca7.tar.bz2
scala-334872e33be8385678697f3d670c8102d38cdca7.zip
Bringing a bit of order to symbol substitution.
Painstakingly winnowed out the most frequently duplicated code sequences related to symbol cloning and substitution. Created canonical methods to perform these actions and documented them. Key methods include: def createFromClonedSymbols[T](syms: List[Symbol], tpe: Type)(creator: (List[Symbol], Type) => T): T def deriveSymbols(syms: List[Symbol], symFn: Symbol => Symbol): List[Symbol] def deriveType(syms: List[Symbol], symFn: Symbol => Symbol)(tpe: Type): Type Many example usages enclosed with commit. I did lots of timing tests, I find no material difference before and after. Actually I won by four seconds in this incarnation: Before - Total time: 7 minutes 55 seconds After - Total time: 7 minutes 51 seconds Review by moors.
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala126
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala33
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala133
-rw-r--r--src/compiler/scala/reflect/internal/transform/Erasure.scala5
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala4
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala36
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala41
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala123
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)