summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/tpe
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala/reflect/internal/tpe')
-rw-r--r--src/reflect/scala/reflect/internal/tpe/FindMembers.scala4
-rw-r--r--src/reflect/scala/reflect/internal/tpe/GlbLubs.scala22
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala46
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala55
5 files changed, 61 insertions, 68 deletions
diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
index 1b00815bca..510d76793e 100644
--- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
@@ -125,9 +125,9 @@ trait FindMembers {
/* Add this member to the final result, unless an already-found member matches it. */
protected def addMemberIfNew(sym: Symbol): Unit
- // Is `sym` a potentially member of `baseClass`?
+ // Is `sym` potentially a member of `baseClass`?
//
- // Q. When does a potential member fail to be a an actual member?
+ // Q. When does a potential member fail to be an actual member?
// A. if it is subsumed by an member in a subclass.
private def isPotentialMember(sym: Symbol, flags: Long, owner: Symbol,
seenFirstNonRefinementClass: Boolean, refinementParents: List[Symbol]): Boolean = {
diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
index 123b44aa05..6d9a9d6649 100644
--- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
+++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
@@ -118,7 +118,7 @@ private[internal] trait GlbLubs {
// ts0 is the 1-dimensional frontier of symbols cutting through 2-dimensional tsBts.
// Invariant: all symbols "under" (closer to the first row) the frontier
// are smaller (according to _.isLess) than the ones "on and beyond" the frontier
- val ts0 = tsBts map (_.head)
+ val ts0 = tsBts map (_.head)
// Is the frontier made up of types with the same symbol?
val isUniformFrontier = (ts0: @unchecked) match {
@@ -136,7 +136,7 @@ private[internal] trait GlbLubs {
mergePrefixAndArgs(ts1, Covariant, depth) match {
case NoType => loop(pretypes, tails)
case tp if strictInference && willViolateRecursiveBounds(tp, ts0, ts1) =>
- log(s"Breaking recursion in lublist, advancing frontier and discaring merged prefix/args from $tp")
+ log(s"Breaking recursion in lublist, advancing frontier and discarding merged prefix/args from $tp")
loop(pretypes, tails)
case tp =>
loop(tp :: pretypes, tails)
@@ -210,24 +210,6 @@ private[internal] trait GlbLubs {
}
}
- private def stripExistentialsAndTypeVars(ts: List[Type]): (List[Type], List[Symbol]) = {
- val quantified = ts flatMap {
- case ExistentialType(qs, _) => qs
- case t => List()
- }
- def stripType(tp: Type): Type = tp match {
- case ExistentialType(_, res) =>
- res
- case tv@TypeVar(_, constr) =>
- if (tv.instValid) stripType(constr.inst)
- else if (tv.untouchable) tv
- else abort("trying to do lub/glb of typevar "+tp)
- case t => t
- }
- val strippedTypes = ts mapConserve stripType
- (strippedTypes, quantified)
- }
-
/** Does this set of types have the same weak lub as
* it does regular lub? This is exposed so lub callers
* can discover whether the trees they are typing will
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index f9b10c90be..990092b749 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -58,7 +58,7 @@ trait TypeComparers {
false
private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean = (
- if (sym1 == sym2)
+ if (sym1 eq sym2)
sym1.hasPackageFlag || sym1.owner.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2
else
(sym1.name == sym2.name) && isUnifiable(pre1, pre2)
@@ -79,7 +79,7 @@ trait TypeComparers {
def isDifferentTypeConstructor(tp1: Type, tp2: Type) = !isSameTypeConstructor(tp1, tp2)
private def isSameTypeConstructor(tr1: TypeRef, tr2: TypeRef): Boolean = (
- (tr1.sym == tr2.sym)
+ (tr1.sym eq tr2.sym)
&& !isDifferentType(tr1.pre, tr2.pre)
)
private def isSameTypeConstructor(tp1: Type, tp2: Type): Boolean = (
@@ -222,7 +222,7 @@ trait TypeComparers {
case SingleType(pre1, sym1) => tp2 match { case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1, pre1, sym2, pre2) ; case _ => false }
case PolyType(ps1, res1) => tp2 match { case PolyType(ps2, res2) => equalTypeParamsAndResult(ps1, res1, ps2, res2) ; case _ => false }
case ExistentialType(qs1, res1) => tp2 match { case ExistentialType(qs2, res2) => equalTypeParamsAndResult(qs1, res1, qs2, res2) ; case _ => false }
- case ThisType(sym1) => tp2 match { case ThisType(sym2) => sym1 == sym2 ; case _ => false }
+ case ThisType(sym1) => tp2 match { case ThisType(sym2) => sym1 eq sym2 ; case _ => false }
case ConstantType(c1) => tp2 match { case ConstantType(c2) => c1 == c2 ; case _ => false }
case NullaryMethodType(res1) => tp2 match { case NullaryMethodType(res2) => res1 =:= res2 ; case _ => false }
case TypeBounds(lo1, hi1) => tp2 match { case TypeBounds(lo2, hi2) => lo1 =:= lo2 && hi1 =:= hi2 ; case _ => false }
@@ -344,7 +344,7 @@ trait TypeComparers {
// in the same class, and the 'x' in the ThisType has in its override chain
// the 'x' in the SuperType, then the types conform.
private def isThisAndSuperSubtype(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
- case (SingleType(ThisType(lpre), v1), SingleType(SuperType(ThisType(rpre), _), v2)) => (lpre == rpre) && (v1.overrideChain contains v2)
+ case (SingleType(ThisType(lpre), v1), SingleType(SuperType(ThisType(rpre), _), v2)) => (lpre eq rpre) && (v1.overrideChain contains v2)
case _ => false
}
@@ -361,8 +361,8 @@ trait TypeComparers {
false
}
- ( tp1.typeSymbol == NothingClass // @M Nothing is subtype of every well-kinded type
- || tp2.typeSymbol == AnyClass // @M Any is supertype of every well-kinded type (@PP: is it? What about continuations plugin?)
+ ( (tp1.typeSymbol eq NothingClass) // @M Nothing is subtype of every well-kinded type
+ || (tp2.typeSymbol eq AnyClass) // @M Any is supertype of every well-kinded type (@PP: is it? What about continuations plugin?)
|| isSub(tp1.normalize, tp2.normalize) && annotationsConform(tp1, tp2) // @M! normalize reduces higher-kinded case to PolyType's
)
}
@@ -394,7 +394,7 @@ trait TypeComparers {
val sym2 = tr2.sym
val pre1 = tr1.pre
val pre2 = tr2.pre
- (((if (sym1 == sym2) phase.erasedTypes || sym1.owner.hasPackageFlag || isSubType(pre1, pre2, depth)
+ (((if (sym1 eq sym2) phase.erasedTypes || sym1.owner.hasPackageFlag || isSubType(pre1, pre2, depth)
else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass &&
(isUnifiable(pre1, pre2) ||
isSameSpecializedSkolem(sym1, sym2, pre1, pre2) ||
@@ -403,7 +403,9 @@ trait TypeComparers {
||
sym2.isClass && {
val base = tr1 baseType sym2
- (base ne tr1) && isSubType(base, tr2, depth)
+ // During bootstrap, `base eq NoType` occurs about 2.5 times as often as `base ne NoType`.
+ // The extra check seems like a worthwhile optimization (about 2.5M useless calls to isSubType saved during that run).
+ (base ne tr1) && (base ne NoType) && isSubType(base, tr2, depth)
}
||
thirdTryRef(tr1, tr2))
@@ -463,7 +465,7 @@ trait TypeComparers {
case SingletonClass => tp1.isStable || fourthTry
case _: ClassSymbol => classOnRight
case _: TypeSymbol if sym2.isDeferred => abstractTypeOnRight(tp2.bounds.lo) || fourthTry
- case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
+ case _: TypeSymbol => retry(normalizePlus(tp1), normalizePlus(tp2))
case _ => fourthTry
}
}
@@ -517,7 +519,7 @@ trait TypeComparers {
* - handle typerefs, refined types, and singleton types.
*/
def fourthTry = {
- def retry(lhs: Type, rhs: Type) = isSubType(lhs, rhs, depth)
+ def retry(lhs: Type, rhs: Type) = ((tp1 ne lhs) || (tp2 ne rhs)) && isSubType(lhs, rhs, depth)
def abstractTypeOnLeft(hi: Type) = isDifferentTypeConstructor(tp1, hi) && retry(hi, tp2)
tp1 match {
@@ -526,22 +528,16 @@ trait TypeComparers {
case TypeRef(_, sym2, _) => sym1 isBottomSubClass sym2
case _ => isSingleType(tp2) && retry(tp1, tp2.widen)
}
- def moduleOnLeft = tp2 match {
- case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
- case _ => false
- }
- def classOnLeft = (
- if (isRawType(tp1)) retry(rawToExistential(tp1), tp2)
- else if (sym1.isModuleClass) moduleOnLeft
- else sym1.isRefinementClass && retry(sym1.info, tp2)
- )
+
sym1 match {
- case NothingClass => true
- case NullClass => nullOnLeft
- case _: ClassSymbol => classOnLeft
- case _: TypeSymbol if sym1.isDeferred => abstractTypeOnLeft(tp1.bounds.hi)
- case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
- case _ => false
+ case NothingClass => true
+ case NullClass => nullOnLeft
+ case _: ClassSymbol if isRawType(tp1) => retry(normalizePlus(tp1), normalizePlus(tp2))
+ case _: ClassSymbol if sym1.isModuleClass => retry(normalizePlus(tp1), normalizePlus(tp2))
+ case _: ClassSymbol if sym1.isRefinementClass => retry(sym1.info, tp2)
+ case _: TypeSymbol if sym1.isDeferred => abstractTypeOnLeft(tp1.bounds.hi)
+ case _: TypeSymbol => retry(normalizePlus(tp1), normalizePlus(tp2))
+ case _ => false
}
case RefinedType(parents, _) => parents exists (retry(_, tp2))
case _: SingletonType => retry(tp1.underlying, tp2)
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index e321a07f51..2697824fd5 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -25,7 +25,7 @@ private[internal] trait TypeConstraints {
// register with the auto-clearing cache manager
perRunCaches.recordCache(this)
- /** Undo all changes to constraints to type variables upto `limit`. */
+ /** Undo all changes to constraints to type variables up to `limit`. */
//OPT this method is public so we can do `manual inlining`
def undoTo(limit: UndoPairs) {
assertCorrectThread()
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 804360b677..0601067d26 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -53,14 +53,6 @@ private[internal] trait TypeMaps {
}
}
- // Set to true for A* => Seq[A]
- // (And it will only rewrite A* in method result types.)
- // This is the pre-existing behavior.
- // Or false for Seq[A] => Seq[A]
- // (It will rewrite A* everywhere but method parameters.)
- // This is the specified behavior.
- protected def etaExpandKeepsStar = false
-
/** Turn any T* types into Seq[T] except when
* in method parameter position.
*/
@@ -74,7 +66,7 @@ private[internal] trait TypeMaps {
case TypeRef(_, RepeatedParamClass, arg :: Nil) =>
seqType(arg)
case _ =>
- if (etaExpandKeepsStar) tp else mapOver(tp)
+ mapOver(tp)
}
}
@@ -320,7 +312,7 @@ private[internal] trait TypeMaps {
* the corresponding class file might still not be read, so we do not
* know what the type parameters of the type are. Therefore
* the conversion of raw types to existential types might not have taken place
- * in ClassFileparser.sigToType (where it is usually done).
+ * in ClassFileParser.sigToType (where it is usually done).
*/
def rawToExistential = new TypeMap {
private var expanded = immutable.Set[Symbol]()
@@ -412,7 +404,7 @@ private[internal] trait TypeMaps {
case _ => super.mapOver(tp)
}
- // Do not discard the types of existential ident's. The
+ // Do not discard the types of existential idents. The
// symbol of the Ident itself cannot be listed in the
// existential's parameters, so the resulting existential
// type would be ill-formed.
@@ -449,12 +441,15 @@ private[internal] trait TypeMaps {
(pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz)
)
- def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap =
- new AsSeenFromMap(pre, clazz)
+ @deprecated("use new AsSeenFromMap instead", "2.12.0")
+ final def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap = new AsSeenFromMap(pre, clazz)
/** A map to compute the asSeenFrom method.
*/
- class AsSeenFromMap(seenFromPrefix: Type, seenFromClass: Symbol) extends TypeMap with KeepOnlyTypeConstraints {
+ class AsSeenFromMap(seenFromPrefix0: Type, seenFromClass: Symbol) extends TypeMap with KeepOnlyTypeConstraints {
+ private val seenFromPrefix: Type = if (seenFromPrefix0.typeSymbolDirect.hasPackageFlag && !seenFromClass.hasPackageFlag)
+ seenFromPrefix0.packageObject.typeOfThis
+ else seenFromPrefix0
// Some example source constructs relevant in asSeenFrom:
//
// object CaptureThis {
@@ -509,6 +504,8 @@ private[internal] trait TypeMaps {
&& isBaseClassOfEnclosingClass(sym.owner)
)
+ private var capturedThisIds = 0
+ private def nextCapturedThisId() = { capturedThisIds += 1; capturedThisIds }
/** Creates an existential representing a type parameter which appears
* in the prefix of a ThisType.
*/
@@ -516,7 +513,7 @@ private[internal] trait TypeMaps {
capturedParams find (_.owner == clazz) match {
case Some(p) => p.tpe
case _ =>
- val qvar = clazz freshExistential nme.SINGLETON_SUFFIX setInfo singletonBounds(pre)
+ val qvar = clazz.freshExistential(nme.SINGLETON_SUFFIX, nextCapturedThisId()) setInfo singletonBounds(pre)
_capturedParams ::= qvar
debuglog(s"Captured This(${clazz.fullNameString}) seen from $seenFromPrefix: ${qvar.defString}")
qvar.tpe
@@ -607,11 +604,26 @@ private[internal] trait TypeMaps {
}
// Does the candidate symbol match the given prefix and class?
- // Since pre may be something like ThisType(A) where trait A { self: B => },
- // we have to test the typeSymbol of the widened type, not pre.typeSymbol, or
- // B will not be considered.
- private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) =
- (clazz == candidate) && (pre.widen.typeSymbol isSubClass clazz)
+ private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) = (clazz == candidate) && {
+ val pre1 = pre match {
+ case tv: TypeVar =>
+ // Needed with existentials in prefixes, e.g. test/files/pos/typevar-in-prefix.scala
+ // Perhaps the base type sequence of a type var should include its bounds?
+ tv.origin
+ case _ => pre
+ }
+ // widen needed (at least) because of https://github.com/scala/scala-dev/issues/166
+ (
+ if (clazz.isRefinementClass)
+ // base type seqs of aliases over refinement types have copied refinement types based on beta reduction
+ // for reliable lookup we need to consult the base type of the type symbol. (example: pos/t8177b.scala)
+ pre1.widen.typeSymbol isSubClass clazz
+ else
+ // In the general case, we look at the base type sequence of the prefix itself,
+ // which can have more concrete base classes than `.typeSymbol.baseClasses` (example: t5294, t6161)
+ pre1.widen.baseTypeIndex(clazz) != -1
+ )
+ }
// Whether the annotation tree currently being mapped over has had a This(_) node rewritten.
private[this] var wroteAnnotation = false
@@ -1009,6 +1021,9 @@ private[internal] trait TypeMaps {
case _ =>
tp.normalize match {
case TypeRef(_, sym1, _) if (sym == sym1) => result = true
+ case refined: RefinedType =>
+ mapOver(tp.prefix)
+ mapOver(refined)
case SingleType(_, sym1) if (sym == sym1) => result = true
case _ => mapOver(tp)
}