@@ -34,6 +34,7 @@ import annotation.tailrec
3434import language .implicitConversions
3535import scala .util .hashing .{ MurmurHash3 => hashing }
3636import config .Printers .{core , typr }
37+ import reporting .trace
3738import java .lang .ref .WeakReference
3839
3940import scala .annotation .internal .sharable
@@ -1074,6 +1075,20 @@ object Types {
10741075 /** Like `dealiasKeepAnnots`, but keeps only refining annotations */
10751076 final def dealiasKeepRefiningAnnots (implicit ctx : Context ): Type = dealias1(keepIfRefining)
10761077
1078+ /** The result of normalization using `tryNormalize`, or the type itself if
1079+ * tryNormlize yields NoType
1080+ */
1081+ final def normalized (implicit ctx : Context ) = {
1082+ val normed = tryNormalize
1083+ if (normed.exists) normed else this
1084+ }
1085+
1086+ /** If this type can be normalized at the top-level by rewriting match types
1087+ * of S[n] types, the result after applying all toplevel normalizations,
1088+ * otherwise NoType
1089+ */
1090+ def tryNormalize (implicit ctx : Context ): Type = NoType
1091+
10771092 private def widenDealias1 (keep : AnnotatedType => Context => Boolean )(implicit ctx : Context ): Type = {
10781093 val res = this .widen.dealias1(keep)
10791094 if (res eq this ) res else res.widenDealias1(keep)
@@ -3264,6 +3279,29 @@ object Types {
32643279 cachedSuper
32653280 }
32663281
3282+ override def tryNormalize (implicit ctx : Context ): Type = tycon match {
3283+ case tycon : TypeRef =>
3284+ def tryMatchAlias = tycon.info match {
3285+ case MatchAlias (alias) =>
3286+ trace(" normalize $this" , show = true ) {
3287+ alias.applyIfParameterized(args).tryNormalize
3288+ }
3289+ case _ =>
3290+ NoType
3291+ }
3292+ if (defn.isTypelevel_S(tycon.symbol) && args.length == 1 ) {
3293+ trace(" normalize S $this" , show = true ) {
3294+ args.head.normalized match {
3295+ case ConstantType (Constant (n : Int )) => ConstantType (Constant (n + 1 ))
3296+ case none => tryMatchAlias
3297+ }
3298+ }
3299+ }
3300+ else tryMatchAlias
3301+ case _ =>
3302+ NoType
3303+ }
3304+
32673305 def lowerBound (implicit ctx : Context ) = tycon.stripTypeVar match {
32683306 case tycon : TypeRef =>
32693307 tycon.info match {
@@ -3574,6 +3612,8 @@ object Types {
35743612 private [this ] var myReduced : Type = null
35753613 private [this ] var reductionContext : mutable.Map [Type , TypeBounds ] = null
35763614
3615+ override def tryNormalize (implicit ctx : Context ): Type = reduced.normalized
3616+
35773617 def reduced (implicit ctx : Context ): Type = {
35783618 val trackingCtx = ctx.fresh.setTypeComparerFn(new TrackingTypeComparer (_))
35793619 val cmp = trackingCtx.typeComparer.asInstanceOf [TrackingTypeComparer ]
@@ -3617,7 +3657,8 @@ object Types {
36173657 if (! Config .cacheMatchReduced || myReduced == null || ! upToDate) {
36183658 record(" MatchType.reduce computed" )
36193659 if (myReduced != null ) record(" MatchType.reduce cache miss" )
3620- myReduced = recur(cases)(trackingCtx)
3660+ myReduced =
3661+ trace(i " reduce match type $this" , show = true ) { recur(cases)(trackingCtx) }
36213662 updateReductionContext()
36223663 }
36233664 myReduced
@@ -3635,12 +3676,8 @@ object Types {
36353676 class CachedMatchType (bound : Type , scrutinee : Type , cases : List [Type ]) extends MatchType (bound, scrutinee, cases)
36363677
36373678 object MatchType {
3638- def apply (bound : Type , scrutinee : Type , cases : List [Type ])(implicit ctx : Context ) = {
3679+ def apply (bound : Type , scrutinee : Type , cases : List [Type ])(implicit ctx : Context ) =
36393680 unique(new CachedMatchType (bound, scrutinee, cases))
3640- // TODO: maybe we should try to reduce match types immediately, but this risks creating illegal
3641- // cycles. So we can do this only if we can prove that the redux is in some sense simpler than
3642- // the original type.
3643- }
36443681 }
36453682
36463683 // ------ ClassInfo, Type Bounds --------------------------------------------------
0 commit comments