@@ -931,6 +931,11 @@ object Types {
931931 */
932932 def stripAnnots (implicit ctx : Context ): Type = this
933933
934+ def rewrapAnnots (tp : Type )(implicit ctx : Context ): Type = tp.stripTypeVar match {
935+ case AnnotatedType (tp1, annot) => AnnotatedType (rewrapAnnots(tp1), annot)
936+ case _ => this
937+ }
938+
934939 /** Strip PolyType prefix */
935940 def stripPoly (implicit ctx : Context ): Type = this match {
936941 case tp : PolyType => tp.resType.stripPoly
@@ -1017,48 +1022,57 @@ object Types {
10171022 this
10181023 }
10191024
1020- private def dealias1 (keepAnnots : Boolean )(implicit ctx : Context ): Type = this match {
1025+ private def dealias1 (keep : AnnotatedType => Context => Boolean )(implicit ctx : Context ): Type = this match {
10211026 case tp : TypeRef =>
10221027 if (tp.symbol.isClass) tp
10231028 else tp.info match {
1024- case TypeAlias (alias) => alias.dealias1(keepAnnots ): @ tailrec
1029+ case TypeAlias (alias) => alias.dealias1(keep ): @ tailrec
10251030 case _ => tp
10261031 }
10271032 case app @ AppliedType (tycon, args) =>
1028- val tycon1 = tycon.dealias1(keepAnnots )
1029- if (tycon1 ne tycon) app.superType.dealias1(keepAnnots ): @ tailrec
1033+ val tycon1 = tycon.dealias1(keep )
1034+ if (tycon1 ne tycon) app.superType.dealias1(keep ): @ tailrec
10301035 else this
10311036 case tp : TypeVar =>
10321037 val tp1 = tp.instanceOpt
1033- if (tp1.exists) tp1.dealias1(keepAnnots ): @ tailrec else tp
1038+ if (tp1.exists) tp1.dealias1(keep ): @ tailrec else tp
10341039 case tp : AnnotatedType =>
1035- val tp1 = tp.tpe.dealias1(keepAnnots )
1036- if (keepAnnots ) tp.derivedAnnotatedType(tp1, tp.annot) else tp1
1040+ val tp1 = tp.tpe.dealias1(keep )
1041+ if (keep(tp)(ctx) ) tp.derivedAnnotatedType(tp1, tp.annot) else tp1
10371042 case tp : LazyRef =>
1038- tp.ref.dealias1(keepAnnots ): @ tailrec
1043+ tp.ref.dealias1(keep ): @ tailrec
10391044 case _ => this
10401045 }
10411046
1047+ /** Follow aliases and dereferences LazyRefs, annotated types and instantiated
1048+ * TypeVars until type is no longer alias type, annotated type, LazyRef,
1049+ * or instantiated type variable.
1050+ */
1051+ final def dealias (implicit ctx : Context ): Type = dealias1(keepNever)
1052+
10421053 /** Follow aliases and dereferences LazyRefs and instantiated TypeVars until type
10431054 * is no longer alias type, LazyRef, or instantiated type variable.
10441055 * Goes through annotated types and rewraps annotations on the result.
10451056 */
1046- final def dealiasKeepAnnots (implicit ctx : Context ): Type =
1047- dealias1(keepAnnots = true )
1057+ final def dealiasKeepAnnots (implicit ctx : Context ): Type = dealias1(keepAlways)
10481058
1049- /** Follow aliases and dereferences LazyRefs, annotated types and instantiated
1050- * TypeVars until type is no longer alias type, annotated type, LazyRef,
1051- * or instantiated type variable.
1052- */
1053- final def dealias (implicit ctx : Context ): Type =
1054- dealias1(keepAnnots = false )
1059+ /** Like `dealiasKeepAnnots`, but keeps only refining annotations */
1060+ final def dealiasKeepRefiningAnnots (implicit ctx : Context ): Type = dealias1(keepIfRefining)
10551061
1056- /** Perform successive widenings and dealiasings until none can be applied anymore */
1057- @ tailrec final def widenDealias (implicit ctx : Context ): Type = {
1058- val res = this .widen.dealias
1059- if (res eq this ) res else res.widenDealias
1062+ private def widenDealias1 (keep : AnnotatedType => Context => Boolean )(implicit ctx : Context ): Type = {
1063+ val res = this .widen.dealias1(keep)
1064+ if (res eq this ) res else res.widenDealias1(keep)
10601065 }
10611066
1067+ /** Perform successive widenings and dealiasings until none can be applied anymore */
1068+ final def widenDealias (implicit ctx : Context ): Type = widenDealias1(keepNever)
1069+
1070+ /** Perform successive widenings and dealiasings while rewrapping annotations, until none can be applied anymore */
1071+ final def widenDealiasKeepAnnots (implicit ctx : Context ): Type = widenDealias1(keepAlways)
1072+
1073+ /** Perform successive widenings and dealiasings while rewrapping refining annotations, until none can be applied anymore */
1074+ final def widenDealiasKeepRefiningAnnots (implicit ctx : Context ): Type = widenDealias1(keepIfRefining)
1075+
10621076 /** Widen from constant type to its underlying non-constant
10631077 * base type.
10641078 */
@@ -1805,8 +1819,8 @@ object Types {
18051819 case arg : TypeBounds =>
18061820 val v = param.paramVariance
18071821 val pbounds = param.paramInfo
1808- if (v > 0 && pbounds.loBound.dealias .isBottomType) TypeAlias (arg.hiBound & rebase(pbounds.hiBound))
1809- else if (v < 0 && pbounds.hiBound.dealias .isTopType) TypeAlias (arg.loBound | rebase(pbounds.loBound))
1822+ if (v > 0 && pbounds.loBound.dealiasKeepAnnots .isBottomType) TypeAlias (arg.hiBound & rebase(pbounds.hiBound))
1823+ else if (v < 0 && pbounds.hiBound.dealiasKeepAnnots .isTopType) TypeAlias (arg.loBound | rebase(pbounds.loBound))
18101824 else arg recoverable_& rebase(pbounds)
18111825 case arg => TypeAlias (arg)
18121826 }
@@ -4165,11 +4179,12 @@ object Types {
41654179 */
41664180 def tryWiden (tp : NamedType , pre : Type ): Type = pre.member(tp.name) match {
41674181 case d : SingleDenotation =>
4168- d.info.dealias match {
4182+ val tp1 = d.info.dealiasKeepAnnots
4183+ tp1.stripAnnots match {
41694184 case TypeAlias (alias) =>
41704185 // if H#T = U, then for any x in L..H, x.T =:= U,
41714186 // hence we can replace with U under all variances
4172- reapply(alias)
4187+ reapply(alias.rewrapAnnots(tp1) )
41734188 case TypeBounds (lo, hi) =>
41744189 // If H#T = _ >: S <: U, then for any x in L..H, S <: x.T <: U,
41754190 // hence we can replace with S..U under all variances
@@ -4595,7 +4610,7 @@ object Types {
45954610 case _ => false
45964611 }
45974612
4598- // ----- Decorator implicits ------ --------------------------------------
4613+ // ----- Helpers and Decorator implicits --------------------------------------
45994614
46004615 implicit def decorateTypeApplications (tpe : Type ): TypeApplications = new TypeApplications (tpe)
46014616
@@ -4608,4 +4623,8 @@ object Types {
46084623 else tps2.nonEmpty && tps1.head.equals(tps2.head, bs) && tps1.tail.equalElements(tps2.tail, bs)
46094624 }
46104625 }
4626+
4627+ private val keepAlways : AnnotatedType => Context => Boolean = _ => _ => true
4628+ private val keepNever : AnnotatedType => Context => Boolean = _ => _ => false
4629+ private val keepIfRefining : AnnotatedType => Context => Boolean = tp => ctx => tp.isRefining(ctx)
46114630}
0 commit comments