summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Types.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala/reflect/internal/Types.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala413
1 files changed, 223 insertions, 190 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 9697e16da7..de82a6a0b2 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -7,7 +7,7 @@ package scala
package reflect
package internal
-import scala.collection.{ mutable, immutable, generic }
+import scala.collection.{ mutable, immutable }
import scala.ref.WeakReference
import mutable.ListBuffer
import Flags._
@@ -462,7 +462,7 @@ trait Types
* the empty list for all other types */
def boundSyms: immutable.Set[Symbol] = emptySymbolSet
- /** Replace formal type parameter symbols with actual type arguments.
+ /** Replace formal type parameter symbols with actual type arguments. ErrorType on arity mismatch.
*
* Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- @M
*/
@@ -589,7 +589,12 @@ trait Types
def nonPrivateMembersAdmitting(admit: Long): Scope = membersBasedOnFlags(BridgeAndPrivateFlags & ~admit, 0)
/** A list of all implicit symbols of this type (defined or inherited) */
- def implicitMembers: Scope = membersBasedOnFlags(BridgeFlags, IMPLICIT)
+ def implicitMembers: Scope = {
+ typeSymbolDirect match {
+ case sym: ModuleClassSymbol => sym.implicitMembers
+ case _ => membersBasedOnFlags(BridgeFlags, IMPLICIT)
+ }
+ }
/** A list of all deferred symbols of this type (defined or inherited) */
def deferredMembers: Scope = membersBasedOnFlags(BridgeFlags, DEFERRED)
@@ -606,6 +611,8 @@ trait Types
def nonPrivateMember(name: Name): Symbol =
memberBasedOnName(name, BridgeAndPrivateFlags)
+ def packageObject: Symbol = member(nme.PACKAGE)
+
/** The non-private member with given name, admitting members with given flags `admit`.
* "Admitting" refers to the fact that members with a PRIVATE, BRIDGE, or VBRIDGE
* flag are usually excluded from findMember results, but supplying any of those flags
@@ -659,7 +666,7 @@ trait Types
)
if (trivial) this
else {
- val m = newAsSeenFromMap(pre.normalize, clazz)
+ val m = new AsSeenFromMap(pre.normalize, clazz)
val tp = m(this)
val tp1 = existentialAbstraction(m.capturedParams, tp)
@@ -1189,7 +1196,6 @@ trait Types
object ThisType extends ThisTypeExtractor {
def apply(sym: Symbol): Type = (
if (!phase.erasedTypes) unique(new UniqueThisType(sym))
- else if (sym.isImplClass) sym.typeOfThis
else sym.tpe_*
)
}
@@ -1207,6 +1213,10 @@ trait Types
private[reflect] var underlyingCache: Type = NoType
private[reflect] var underlyingPeriod = NoPeriod
+ private[Types] def invalidateSingleTypeCaches(): Unit = {
+ underlyingCache = NoType
+ underlyingPeriod = NoPeriod
+ }
override def underlying: Type = {
val cache = underlyingCache
if (underlyingPeriod == currentPeriod && cache != null) cache
@@ -1347,6 +1357,12 @@ trait Types
private[reflect] var baseTypeSeqPeriod = NoPeriod
private[reflect] var baseClassesCache: List[Symbol] = _
private[reflect] var baseClassesPeriod = NoPeriod
+ private[Types] def invalidatedCompoundTypeCaches() {
+ baseTypeSeqCache = null
+ baseTypeSeqPeriod = NoPeriod
+ baseClassesCache = null
+ baseClassesPeriod = NoPeriod
+ }
override def baseTypeSeq: BaseTypeSeq = {
val cached = baseTypeSeqCache
@@ -1600,7 +1616,14 @@ trait Types
private var normalized: Type = _
private def normalizeImpl = {
// TODO see comments around def intersectionType and def merge
- def flatten(tps: List[Type]): List[Type] = tps flatMap { case RefinedType(parents, ds) if ds.isEmpty => flatten(parents) case tp => List(tp) }
+ // SI-8575 The dealias is needed here to keep subtyping transitive, example in run/t8575b.scala
+ def flatten(tps: List[Type]): List[Type] = {
+ def dealiasRefinement(tp: Type) = if (tp.dealias.isInstanceOf[RefinedType]) tp.dealias else tp
+ tps map dealiasRefinement flatMap {
+ case RefinedType(parents, ds) if ds.isEmpty => flatten(parents)
+ case tp => List(tp)
+ }
+ }
val flattened = flatten(parents).distinct
if (decls.isEmpty && hasLength(flattened, 1)) {
flattened.head
@@ -1843,53 +1866,13 @@ trait Types
override def isHigherKinded = false
override def typeParams = Nil
- override def transform(tp: Type): Type = {
- // This situation arises when a typevar is encountered for which
- // too little information is known to determine its kind, and
- // it later turns out not to have kind *. See SI-4070. Only
- // logging it for now.
- val tparams = sym.typeParams
- if (tparams.size != args.size)
- devWarning(s"$this.transform($tp), but tparams.isEmpty and args=$args")
- def asSeenFromInstantiated(tp: Type) =
- asSeenFromOwner(tp).instantiateTypeParams(tparams, args)
- // If we're called with a poly type, and we were to run the `asSeenFrom`, over the entire
- // type, we can end up with new symbols for the type parameters (clones from TypeMap).
- // The subsequent substitution of type arguments would fail. This problem showed up during
- // the fix for SI-8046, however the solution taken there wasn't quite right, and led to
- // SI-8170.
- //
- // Now, we detect the PolyType before both the ASF *and* the substitution, and just operate
- // on the result type.
- //
- // TODO: Revisit this and explore the questions raised:
- //
- // AM: I like this better than the old code, but is there any way the tparams would need the ASF treatment as well?
- // JZ: I think its largely irrelevant, as they are no longer referred to in the result type.
- // In fact, you can get away with returning a type of kind * here and the sky doesn't fall:
- // `case PolyType(`tparams`, result) => asSeenFromInstantiated(result)`
- // But I thought it was better to retain the kind.
- // AM: I've been experimenting with apply-type-args-then-ASF, but running into cycles.
- // In general, it seems iffy the tparams can never occur in the result
- // then we might as well represent the type as a no-arg typeref.
- // AM: I've also been trying to track down uses of transform (pretty generic name for something that
- // does not seem that widely applicable).
- // It's kind of a helper for computing baseType (since it tries to propagate our type args to some
- // other type, which has to be related to this type for that to make sense).
- //
- tp match {
- case PolyType(`tparams`, result) => PolyType(tparams, asSeenFromInstantiated(result))
- case _ => asSeenFromInstantiated(tp)
- }
- }
-
// note: does not go through typeRef. There's no need to because
// neither `pre` nor `sym` changes. And there's a performance
// advantage to call TypeRef directly.
override def typeConstructor = TypeRef(pre, sym, Nil)
}
- class ModuleTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) with ClassTypeRef {
+ class ModuleTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) {
require(sym.isModuleClass, sym)
private[this] var narrowedCache: Type = _
override def narrow = {
@@ -1898,6 +1881,10 @@ trait Types
narrowedCache
}
+ override private[Types] def invalidateTypeRefCaches(): Unit = {
+ super.invalidateTypeRefCaches()
+ narrowedCache = null
+ }
override protected def finishPrefix(rest: String) = objectPrefix + rest
override def directObjectString = super.safeToString
override def toLongString = toString
@@ -1908,12 +1895,12 @@ trait Types
require(sym.isPackageClass, sym)
override protected def finishPrefix(rest: String) = packagePrefix + rest
}
- class RefinementTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) with ClassTypeRef {
+ class RefinementTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) {
require(sym.isRefinementClass, sym)
// I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
override protected def normalizeImpl: Type = sym.info.normalize
- override protected def finishPrefix(rest: String) = "" + thisInfo
+ override protected def finishPrefix(rest: String) = "" + sym.info
}
class NoArgsTypeRef(pre0: Type, sym0: Symbol) extends TypeRef(pre0, sym0, Nil) {
@@ -1924,7 +1911,6 @@ trait Types
// represented as existential types.
override def isHigherKinded = (typeParams ne Nil)
override def typeParams = if (isDefinitionsInitialized) sym.typeParams else sym.unsafeTypeParams
- private def isRaw = !phase.erasedTypes && isRawIfWithoutArgs(sym)
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
if (isHigherKinded) {
@@ -1937,17 +1923,6 @@ trait Types
else
super.instantiateTypeParams(formals, actuals)
- override def transform(tp: Type): Type = {
- val res = asSeenFromOwner(tp)
- if (isHigherKinded && !isRaw)
- res.instantiateTypeParams(typeParams, dummyArgs)
- else
- res
- }
-
- override def transformInfo(tp: Type): Type =
- appliedType(asSeenFromOwner(tp), dummyArgs)
-
override def narrow =
if (sym.isModuleClass) singleType(pre, sym.sourceModule)
else super.narrow
@@ -1959,65 +1934,75 @@ trait Types
if (isHigherKinded) etaExpand else super.normalizeImpl
}
- trait ClassTypeRef extends TypeRef {
- // !!! There are scaladoc-created symbols arriving which violate this require.
- // require(sym.isClass, sym)
-
- override def baseType(clazz: Symbol): Type =
- if (sym == clazz) this
- else transform(sym.info.baseType(clazz))
- }
-
trait NonClassTypeRef extends TypeRef {
require(sym.isNonClassType, sym)
- /* Syncnote: These are pure caches for performance; no problem to evaluate these
- * several times. Hence, no need to protected with synchronized in a multi-threaded
- * usage scenario.
- */
+ /** Syncnote: These are pure caches for performance; no problem to evaluate these
+ * several times. Hence, no need to protected with synchronized in a multi-threaded
+ * usage scenario.
+ */
private var relativeInfoCache: Type = _
- private var relativeInfoPeriod: Period = NoPeriod
+ private var relativeInfoCacheValidForPeriod: Period = NoPeriod
+ private var relativeInfoCacheValidForSymInfo: Type = _
- private[Types] def relativeInfo = /*trace(s"relativeInfo(${safeToString}})")*/{
- if (relativeInfoPeriod != currentPeriod) {
- val memberInfo = pre.memberInfo(sym)
- relativeInfoCache = transformInfo(memberInfo)
- relativeInfoPeriod = currentPeriod
+ override private[Types] def invalidateTypeRefCaches(): Unit = {
+ super.invalidateTypeRefCaches()
+ relativeInfoCache = NoType
+ relativeInfoCacheValidForPeriod = NoPeriod
+ relativeInfoCacheValidForSymInfo = null
+ }
+
+ final override protected def relativeInfo = {
+ val symInfo = sym.info
+ if ((relativeInfoCache eq null) || (relativeInfoCacheValidForSymInfo ne symInfo) || (relativeInfoCacheValidForPeriod != currentPeriod)) {
+ relativeInfoCache = super.relativeInfo
+
+ if (this.isInstanceOf[AbstractTypeRef]) validateRelativeInfo()
+
+ relativeInfoCacheValidForSymInfo = symInfo
+ relativeInfoCacheValidForPeriod = currentPeriod
}
relativeInfoCache
}
- override def baseType(clazz: Symbol): Type =
- if (sym == clazz) this else baseTypeOfNonClassTypeRef(this, clazz)
+ private def validateRelativeInfo(): Unit = relativeInfoCache match {
+ // If a subtyping cycle is not detected here, we'll likely enter an infinite
+ // loop before a sensible error can be issued. SI-5093 is one example.
+ case x: SubType if x.supertype eq this =>
+ relativeInfoCache = null
+ throw new RecoverableCyclicReference(sym)
+ case _ =>
+ }
}
- protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = try {
- basetypeRecursions += 1
- if (basetypeRecursions < LogPendingBaseTypesThreshold)
- tpe.relativeInfo.baseType(clazz)
- else if (pendingBaseTypes contains tpe)
- if (clazz == AnyClass) clazz.tpe else NoType
- else
- try {
- pendingBaseTypes += tpe
- tpe.relativeInfo.baseType(clazz)
- } finally {
- pendingBaseTypes -= tpe
- }
- } finally {
- basetypeRecursions -= 1
- }
trait AliasTypeRef extends NonClassTypeRef {
require(sym.isAliasType, sym)
override def dealias = if (typeParamsMatchArgs) betaReduce.dealias else super.dealias
override def narrow = normalize.narrow
- override def thisInfo = normalize
override def prefix = if (this ne normalize) normalize.prefix else pre
override def termSymbol = if (this ne normalize) normalize.termSymbol else super.termSymbol
override def typeSymbol = if (this ne normalize) normalize.typeSymbol else sym
+ override protected[Types] def parentsImpl: List[Type] = normalize.parents map relativize
+
+ // `baseClasses` is sensitive to type args when referencing type members
+ // consider `type foo[x] = x`, `typeOf[foo[String]].baseClasses` should be the same as `typeOf[String].baseClasses`,
+ // which would be lost by looking at `sym.info` without propagating args
+ // since classes cannot be overridden, the prefix can be ignored
+ // (in fact, taking the prefix into account by replacing `normalize`
+ // with `relativeInfo` breaks pos/t8177g.scala, which is probably a bug, but a tricky one...
+ override def baseClasses = normalize.baseClasses
+
+ // similar reasoning holds here as for baseClasses
+ // as another example, consider the type alias `Foo` in `class O { o => type Foo = X { val bla: o.Bar }; type Bar }`
+ // o1.Foo and o2.Foo have different decls `val bla: o1.Bar` versus `val bla: o2.Bar`
+ // In principle, you should only call `sym.info.decls` when you know `sym.isClass`,
+ // and you should `relativize` the infos of the resulting members.
+ // The latter is certainly violated in multiple spots in the codebase (the members are usually transformed correctly, though).
+ override def decls: Scope = normalize.decls
+
// beta-reduce, but don't do partial application -- cycles have been checked in typeRef
override protected def normalizeImpl =
if (typeParamsMatchArgs) betaReduce.normalize
@@ -2040,7 +2025,7 @@ trait Types
//
// this crashes pos/depmet_implicit_tpbetareduce.scala
// appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner)
- override def betaReduce = transform(sym.info.resultType)
+ override def betaReduce = relativize(sym.info.resultType)
/** SI-3731, SI-8177: when prefix is changed to `newPre`, maintain consistency of prefix and sym
* (where the symbol refers to a declaration "embedded" in the prefix).
@@ -2090,27 +2075,13 @@ trait Types
trait AbstractTypeRef extends NonClassTypeRef {
require(sym.isAbstractType, sym)
- /** Syncnote: Pure performance caches; no need to synchronize in multi-threaded environment
- */
- private var symInfoCache: Type = _
- private var thisInfoCache: Type = _
+ override def baseClasses = relativeInfo.baseClasses
+ override def decls = relativeInfo.decls
+ override def bounds = relativeInfo.bounds
+
+ override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = bounds.hi.baseTypeSeq prepend this
+ override protected[Types] def parentsImpl: List[Type] = relativeInfo.parents
- override def thisInfo = {
- val symInfo = sym.info
- if (thisInfoCache == null || (symInfo ne symInfoCache)) {
- symInfoCache = symInfo
- thisInfoCache = transformInfo(symInfo) match {
- // If a subtyping cycle is not detected here, we'll likely enter an infinite
- // loop before a sensible error can be issued. SI-5093 is one example.
- case x: SubType if x.supertype eq this =>
- throw new RecoverableCyclicReference(sym)
- case tp => tp
- }
- }
- thisInfoCache
- }
- override def bounds = thisInfo.bounds
- override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this
override def kind = "AbstractTypeRef"
}
@@ -2128,9 +2099,12 @@ trait Types
trivial = fromBoolean(!sym.isTypeParameter && pre.isTrivial && areTrivialTypes(args))
toBoolean(trivial)
}
- private[scala] def invalidateCaches(): Unit = {
+ private[Types] def invalidateTypeRefCaches(): Unit = {
+ parentsCache = null
parentsPeriod = NoPeriod
+ baseTypeSeqCache = null
baseTypeSeqPeriod = NoPeriod
+ normalized = null
}
private[reflect] var parentsCache: List[Type] = _
private[reflect] var parentsPeriod = NoPeriod
@@ -2151,11 +2125,91 @@ trait Types
finalizeHash(h, 2)
}
+ // interpret symbol's info in terms of the type's prefix and type args
+ protected def relativeInfo: Type = appliedType(sym.info.asSeenFrom(pre, sym.owner), argsOrDummies)
+
// @M: propagate actual type params (args) to `tp`, by replacing
// formal type parameters with actual ones. If tp is higher kinded,
// the "actual" type arguments are types that simply reference the
// corresponding type parameters (unbound type variables)
- def transform(tp: Type): Type
+ //
+ // NOTE: for performance, as well as correctness, we do not attempt
+ // to reframe trivial types in terms of our prefix and args.
+ // asSeenFrom, by construction, is the identity for trivial types,
+ // and substitution cannot change them either (abstract types are non-trivial, specifically because they may need to be replaced)
+ // For correctness, the result for `tp == NoType` must be `NoType`,
+ // if we don't shield against this, and apply instantiateTypeParams to it,
+ // this would result in an ErrorType, which behaves differently during subtyping
+ // (and thus on recursion, subtyping would go from false -- since a NoType is involved --
+ // to true, as ErrorType is always a sub/super type....)
+ final def relativize(tp: Type): Type =
+ if (tp.isTrivial) tp
+ else if (args.isEmpty && (phase.erasedTypes || !isHigherKinded || isRawIfWithoutArgs(sym))) tp.asSeenFrom(pre, sym.owner)
+ else {
+ // The type params and type args should always match in length,
+ // though a mismatch can arise when a typevar is encountered for which
+ // too little information is known to determine its kind, and
+ // it later turns out not to have kind *. See SI-4070.
+ val formals = sym.typeParams
+
+ // If we're called with a poly type, and we were to run the `asSeenFrom`, over the entire
+ // type, we can end up with new symbols for the type parameters (clones from TypeMap).
+ // The subsequent substitution of type arguments would fail. This problem showed up during
+ // the fix for SI-8046, however the solution taken there wasn't quite right, and led to
+ // SI-8170.
+ //
+ // Now, we detect the PolyType before both the ASF *and* the substitution, and just operate
+ // on the result type.
+ //
+ // TODO: Revisit this and explore the questions raised:
+ //
+ // AM: I like this better than the old code, but is there any way the tparams would need the ASF treatment as well?
+ // JZ: I think its largely irrelevant, as they are no longer referred to in the result type.
+ // In fact, you can get away with returning a type of kind * here and the sky doesn't fall:
+ // `case PolyType(`tparams`, result) => asSeenFromInstantiated(result)`
+ // But I thought it was better to retain the kind.
+ // AM: I've been experimenting with apply-type-args-then-ASF, but running into cycles.
+ // In general, it seems iffy the tparams can never occur in the result
+ // then we might as well represent the type as a no-arg typeref.
+ // AM: I've also been trying to track down uses of transform (pretty generic name for something that
+ // does not seem that widely applicable).
+ // It's kind of a helper for computing baseType (since it tries to propagate our type args to some
+ // other type, which has to be related to this type for that to make sense).
+ //
+ def seenFromOwnerInstantiated(tp: Type): Type =
+ tp.asSeenFrom(pre, sym.owner).instantiateTypeParams(formals, argsOrDummies)
+
+ tp match {
+ case PolyType(`formals`, result) => PolyType(formals, seenFromOwnerInstantiated(result))
+ case _ => seenFromOwnerInstantiated(tp)
+ }
+ }
+
+ private def argsOrDummies = if (args.isEmpty) dummyArgs else args
+
+ final override def baseType(clazz: Symbol): Type =
+ if (clazz eq sym) this
+ // NOTE: this first goes to requested base type, *then* does asSeenFrom prefix & instantiates args
+ else if (sym.isClass) relativize(sym.info.baseType(clazz))
+ else baseTypeOfNonClassTypeRef(clazz)
+
+ // two differences with class type basetype:
+ // (1) first relativize the type, then go to the requested base type
+ // (2) cache for cycle robustness
+ private def baseTypeOfNonClassTypeRef(clazz: Symbol) =
+ try {
+ basetypeRecursions += 1
+ if (basetypeRecursions >= LogPendingBaseTypesThreshold) baseTypeOfNonClassTypeRefLogged(clazz)
+ else relativeInfo.baseType(clazz)
+ } finally basetypeRecursions -= 1
+
+ private def baseTypeOfNonClassTypeRefLogged(clazz: Symbol) =
+ if (pendingBaseTypes add this) try relativeInfo.baseType(clazz) finally { pendingBaseTypes remove this }
+ // TODO: is this optimization for AnyClass worth it? (or is it playing last-ditch cycle defense?)
+ // NOTE: for correctness, it only applies for non-class types
+ // (e.g., a package class should not get AnyTpe as its supertype, ever)
+ else if (clazz eq AnyClass) AnyTpe
+ else NoType
// eta-expand, subtyping relies on eta-expansion of higher-kinded types
protected def normalizeImpl: Type = if (isHigherKinded) etaExpand else super.normalize
@@ -2188,21 +2242,16 @@ trait Types
// (they are allowed to be rebound more liberally)
def coevolveSym(pre1: Type): Symbol = sym
- //@M! use appliedType on the polytype that represents the bounds (or if aliastype, the rhs)
- def transformInfo(tp: Type): Type = appliedType(asSeenFromOwner(tp), args)
-
- def thisInfo = sym.info
def initializedTypeParams = sym.info.typeParams
def typeParamsMatchArgs = sameLength(initializedTypeParams, args)
- def asSeenFromOwner(tp: Type) = tp.asSeenFrom(pre, sym.owner)
- override def baseClasses = thisInfo.baseClasses
+
override def baseTypeSeqDepth = baseTypeSeq.maxDepth
override def prefix = pre
override def termSymbol = super.termSymbol
override def termSymbolDirect = super.termSymbol
override def typeArgs = args
- override def typeOfThis = transform(sym.typeOfThis)
+ override def typeOfThis = relativize(sym.typeOfThis)
override def typeSymbol = sym
override def typeSymbolDirect = sym
@@ -2215,22 +2264,26 @@ trait Types
}
}
- override def decls: Scope = {
- sym.info match {
- case TypeRef(_, sym1, _) =>
- assert(sym1 != sym, this) // @MAT was != typeSymbol
- case _ =>
- }
- thisInfo.decls
- }
+ protected[Types] def parentsImpl: List[Type] = sym.info.parents map relativize
+
+ // Since type parameters cannot occur in super types, no need to relativize before looking at base *classes*.
+ // Similarly, our prefix can occur in super class types, but it cannot influence which classes those types resolve to.
+ // For example, `class Outer { outer => class Inner extends outer.Foo; class Foo }`
+ // `outer`'s value has no impact on which `Foo` is selected, since classes cannot be overridden.
+ // besides being faster, we can't use relativeInfo because it causes cycles
+ override def baseClasses = sym.info.baseClasses
+
+ // in principle, we should use `relativeInfo.decls`, but I believe all uses of `decls` will correctly `relativize` the individual members
+ override def decls: Scope = sym.info.decls
+
protected[Types] def baseTypeSeqImpl: BaseTypeSeq =
if (sym.info.baseTypeSeq exists (_.typeSymbolDirect.isAbstractType))
// SI-8046 base type sequence might have more elements in a subclass, we can't map it element wise.
- transform(sym.info).baseTypeSeq
+ relativize(sym.info).baseTypeSeq
else
// Optimization: no abstract types, we can compute the BTS of this TypeRef as an element-wise map
// of the BTS of the referenced symbol.
- sym.info.baseTypeSeq map transform
+ sym.info.baseTypeSeq map relativize
override def baseTypeSeq: BaseTypeSeq = {
val cache = baseTypeSeqCache
@@ -2261,9 +2314,10 @@ trait Types
)
protected def finishPrefix(rest: String) = (
if (sym.isInitialized && sym.isAnonymousClass && !phase.erasedTypes)
- parentsString(thisInfo.parents) + refinementString
+ parentsString(sym.info.parents) + refinementString
else rest
- )
+ )
+
private def noArgsString = finishPrefix(preString + sym.nameString)
private def tupleTypeString: String = args match {
case Nil => noArgsString
@@ -2325,10 +2379,10 @@ trait Types
// No longer defined as anonymous classes in `object TypeRef` to avoid an unnecessary outer pointer.
private final class AliasArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with AliasTypeRef
private final class AbstractArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with AbstractTypeRef
- private final class ClassArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with ClassTypeRef
+ private final class ClassArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args)
private final class AliasNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with AliasTypeRef
private final class AbstractNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with AbstractTypeRef
- private final class ClassNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with ClassTypeRef
+ private final class ClassNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym)
object TypeRef extends TypeRefExtractor {
def apply(pre: Type, sym: Symbol, args: List[Type]): Type = unique({
@@ -2353,7 +2407,7 @@ trait Types
if (period != currentPeriod) {
tpe.parentsPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- tpe.parentsCache = tpe.thisInfo.parents map tpe.transform
+ tpe.parentsCache = tpe.parentsImpl
} else if (tpe.parentsCache == null) { // seems this can happen if things are corrupted enough, see #2641
tpe.parentsCache = List(AnyTpe)
}
@@ -2408,7 +2462,6 @@ trait Types
def isImplicit = (params ne Nil) && params.head.isImplicit
def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized?
- //assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
override def paramSectionCount: Int = resultType.paramSectionCount + 1
override def paramss: List[List[Symbol]] = params :: resultType.paramss
@@ -2458,6 +2511,8 @@ trait Types
override def isJava = true
}
+ // TODO: rename so it's more appropriate for the type that is for a method without argument lists
+ // ("nullary" erroneously implies it has an argument list with zero arguments, it actually has zero argument lists)
case class NullaryMethodType(override val resultType: Type) extends Type with NullaryMethodTypeApi {
override def isTrivial = resultType.isTrivial && (resultType eq resultType.withoutAnnotations)
override def prefix: Type = resultType.prefix
@@ -3877,6 +3932,8 @@ trait Types
et.withTypeVars(isConsistent(_, tp2))
case (_, et: ExistentialType) =>
et.withTypeVars(isConsistent(tp1, _))
+ case (_, _) =>
+ throw new MatchError((tp1, tp2))
}
def check(tp1: Type, tp2: Type) = (
@@ -3889,54 +3946,15 @@ trait Types
check(tp1, tp2) && check(tp2, tp1)
}
- /** Does a pattern of type `patType` need an outer test when executed against
- * selector type `selType` in context defined by `currentOwner`?
- */
- def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
- def createDummyClone(pre: Type): Type = {
- val dummy = currentOwner.enclClass.newValue(nme.ANYname).setInfo(pre.widen)
- singleType(ThisType(currentOwner.enclClass), dummy)
- }
- def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
- case SingleType(pre1, sym1) =>
- if (sym1.isModule && sym1.isStatic) {
- NoType
- } else if (sym1.isModule && sym.owner == sym1.moduleClass) {
- val pre2 = maybeCreateDummyClone(pre1, sym1)
- if (pre2 eq NoType) pre2
- else singleType(pre2, sym1)
- } else {
- createDummyClone(pre)
- }
- case ThisType(clazz) =>
- if (clazz.isModuleClass)
- maybeCreateDummyClone(clazz.typeOfThis, sym)
- else if (sym.owner == clazz && (sym.hasFlag(PRIVATE) || sym.privateWithin == clazz))
- NoType
- else
- createDummyClone(pre)
- case _ =>
- NoType
- }
- // See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
- // generates an outer test based on `patType.prefix` with automatically dealises.
- patType.dealias match {
- case TypeRef(pre, sym, args) =>
- val pre1 = maybeCreateDummyClone(pre, sym)
- (pre1 ne NoType) && isPopulated(copyTypeRef(patType, pre1, sym, args), selType)
- case _ =>
- false
- }
- }
-
- def normalizePlus(tp: Type) = (
+ def normalizePlus(tp: Type): Type = {
if (isRawType(tp)) rawToExistential(tp)
else tp.normalize match {
- // Unify the two representations of module classes
- case st @ SingleType(_, sym) if sym.isModule => st.underlying.normalize
- case _ => tp.normalize
+ // Unify the representations of module classes
+ case st@SingleType(_, sym) if sym.isModule => st.underlying.normalize
+ case st@ThisType(sym) if sym.isModuleClass => normalizePlus(st.underlying)
+ case _ => tp.normalize
}
- )
+ }
/*
todo: change to:
@@ -4555,6 +4573,21 @@ trait Types
if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyTpe
else tp
+ def invalidateTreeTpeCaches(tree: Tree, updatedSyms: List[Symbol]) = if (updatedSyms.nonEmpty)
+ for (t <- tree if t.tpe != null)
+ for (tp <- t.tpe) {
+ invalidateCaches(tp, updatedSyms)
+ }
+
+ def invalidateCaches(t: Type, updatedSyms: List[Symbol]) =
+ t match {
+ case st: SingleType if updatedSyms.contains(st.sym) => st.invalidateSingleTypeCaches()
+ case tr: TypeRef if updatedSyms.contains(tr.sym) => tr.invalidateTypeRefCaches()
+ case ct: CompoundType if ct.baseClasses.exists(updatedSyms.contains) => ct.invalidatedCompoundTypeCaches()
+ case _ =>
+ }
+
+
val shorthands = Set(
"scala.collection.immutable.List",
"scala.collection.immutable.Nil",