diff options
Diffstat (limited to 'src/reflect/scala/reflect/internal/tpe')
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) } |