@@ -931,6 +931,11 @@ object Types {
931
931
*/
932
932
def stripAnnots (implicit ctx : Context ): Type = this
933
933
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
+
934
939
/** Strip PolyType prefix */
935
940
def stripPoly (implicit ctx : Context ): Type = this match {
936
941
case tp : PolyType => tp.resType.stripPoly
@@ -1017,48 +1022,57 @@ object Types {
1017
1022
this
1018
1023
}
1019
1024
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 {
1021
1026
case tp : TypeRef =>
1022
1027
if (tp.symbol.isClass) tp
1023
1028
else tp.info match {
1024
- case TypeAlias (alias) => alias.dealias1(keepAnnots ): @ tailrec
1029
+ case TypeAlias (alias) => alias.dealias1(keep ): @ tailrec
1025
1030
case _ => tp
1026
1031
}
1027
1032
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
1030
1035
else this
1031
1036
case tp : TypeVar =>
1032
1037
val tp1 = tp.instanceOpt
1033
- if (tp1.exists) tp1.dealias1(keepAnnots ): @ tailrec else tp
1038
+ if (tp1.exists) tp1.dealias1(keep ): @ tailrec else tp
1034
1039
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
1037
1042
case tp : LazyRef =>
1038
- tp.ref.dealias1(keepAnnots ): @ tailrec
1043
+ tp.ref.dealias1(keep ): @ tailrec
1039
1044
case _ => this
1040
1045
}
1041
1046
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
+
1042
1053
/** Follow aliases and dereferences LazyRefs and instantiated TypeVars until type
1043
1054
* is no longer alias type, LazyRef, or instantiated type variable.
1044
1055
* Goes through annotated types and rewraps annotations on the result.
1045
1056
*/
1046
- final def dealiasKeepAnnots (implicit ctx : Context ): Type =
1047
- dealias1(keepAnnots = true )
1057
+ final def dealiasKeepAnnots (implicit ctx : Context ): Type = dealias1(keepAlways)
1048
1058
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)
1055
1061
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)
1060
1065
}
1061
1066
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
+
1062
1076
/** Widen from constant type to its underlying non-constant
1063
1077
* base type.
1064
1078
*/
@@ -1805,8 +1819,8 @@ object Types {
1805
1819
case arg : TypeBounds =>
1806
1820
val v = param.paramVariance
1807
1821
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))
1810
1824
else arg recoverable_& rebase(pbounds)
1811
1825
case arg => TypeAlias (arg)
1812
1826
}
@@ -4165,11 +4179,12 @@ object Types {
4165
4179
*/
4166
4180
def tryWiden (tp : NamedType , pre : Type ): Type = pre.member(tp.name) match {
4167
4181
case d : SingleDenotation =>
4168
- d.info.dealias match {
4182
+ val tp1 = d.info.dealiasKeepAnnots
4183
+ tp1.stripAnnots match {
4169
4184
case TypeAlias (alias) =>
4170
4185
// if H#T = U, then for any x in L..H, x.T =:= U,
4171
4186
// hence we can replace with U under all variances
4172
- reapply(alias)
4187
+ reapply(alias.rewrapAnnots(tp1) )
4173
4188
case TypeBounds (lo, hi) =>
4174
4189
// If H#T = _ >: S <: U, then for any x in L..H, S <: x.T <: U,
4175
4190
// hence we can replace with S..U under all variances
@@ -4595,7 +4610,7 @@ object Types {
4595
4610
case _ => false
4596
4611
}
4597
4612
4598
- // ----- Decorator implicits ------ --------------------------------------
4613
+ // ----- Helpers and Decorator implicits --------------------------------------
4599
4614
4600
4615
implicit def decorateTypeApplications (tpe : Type ): TypeApplications = new TypeApplications (tpe)
4601
4616
@@ -4608,4 +4623,8 @@ object Types {
4608
4623
else tps2.nonEmpty && tps1.head.equals(tps2.head, bs) && tps1.tail.equalElements(tps2.tail, bs)
4609
4624
}
4610
4625
}
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)
4611
4630
}
0 commit comments