@@ -490,14 +490,7 @@ object Types extends TypeUtils {
490490 case _ => false
491491
492492 /** Does this application expand to a match type? */
493- def isMatchAlias (using Context ): Boolean = underlyingMatchType.exists
494-
495- def underlyingMatchType (using Context ): Type = stripped match {
496- case tp : MatchType => tp
497- case tp : HKTypeLambda => tp.resType.underlyingMatchType
498- case tp : AppliedType => tp.underlyingMatchType
499- case _ => NoType
500- }
493+ def isMatchAlias (using Context ): Boolean = underlyingNormalizable.isMatch
501494
502495 /** Is this a higher-kinded type lambda with given parameter variances?
503496 * These lambdas are used as the RHS of higher-kinded abstract types or
@@ -1550,19 +1543,24 @@ object Types extends TypeUtils {
15501543 }
15511544 deskolemizer(this )
15521545
1553- /** The result of normalization using `tryNormalize`, or the type itself if
1554- * tryNormlize yields NoType
1546+ /** The result of normalization, or the type itself if none apply. */
1547+ final def normalized (using Context ): Type = tryNormalize.orElse(this )
1548+
1549+ /** If this type has an underlying match type or applied compiletime.ops,
1550+ * then the result after applying all toplevel normalizations, otherwise NoType.
15551551 */
1556- final def normalized (using Context ): Type = {
1557- val normed = tryNormalize
1558- if (normed.exists) normed else this
1559- }
1552+ def tryNormalize (using Context ): Type = underlyingNormalizable match
1553+ case mt : MatchType => mt.reduced.normalized
1554+ case tp : AppliedType => tp.tryCompiletimeConstantFold
1555+ case _ => NoType
15601556
1561- /** If this type can be normalized at the top-level by rewriting match types
1562- * of S[n] types, the result after applying all toplevel normalizations,
1563- * otherwise NoType
1557+ /** Perform successive strippings, and beta-reductions of applied types until
1558+ * a match type or applied compiletime.ops is reached, if any, otherwise NoType.
15641559 */
1565- def tryNormalize (using Context ): Type = NoType
1560+ def underlyingNormalizable (using Context ): Type = stripped.stripLazyRef match
1561+ case tp : MatchType => tp
1562+ case tp : AppliedType => tp.underlyingNormalizable
1563+ case _ => NoType
15661564
15671565 private def widenDealias1 (keep : AnnotatedType => Context ?=> Boolean )(using Context ): Type = {
15681566 val res = this .widen.dealias1(keep, keepOpaques = false )
@@ -3258,8 +3256,6 @@ object Types extends TypeUtils {
32583256 private var myRef : Type | Null = null
32593257 private var computed = false
32603258
3261- override def tryNormalize (using Context ): Type = ref.tryNormalize
3262-
32633259 def ref (using Context ): Type =
32643260 if computed then
32653261 if myRef == null then
@@ -4625,8 +4621,8 @@ object Types extends TypeUtils {
46254621 private var myEvalRunId : RunId = NoRunId
46264622 private var myEvalued : Type = uninitialized
46274623
4628- private var validUnderlyingMatch : Period = Nowhere
4629- private var cachedUnderlyingMatch : Type = uninitialized
4624+ private var validUnderlyingNormalizable : Period = Nowhere
4625+ private var cachedUnderlyingNormalizable : Type = uninitialized
46304626
46314627 def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
46324628 if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
@@ -4690,37 +4686,25 @@ object Types extends TypeUtils {
46904686 case nil => x
46914687 foldArgs(op(x, tycon), args)
46924688
4693- /** Exists if the tycon is a TypeRef of an alias with an underlying match type.
4694- * Anything else should have already been reduced in `appliedTo` by the TypeAssigner.
4689+ /** Exists if the tycon is a TypeRef of an alias with an underlying match type,
4690+ * or a compiletime applied type. Anything else should have already been
4691+ * reduced in `appliedTo` by the TypeAssigner. This may reduce several
4692+ * HKTypeLambda applications before the underlying normalizable type is reached.
46954693 */
4696- override def underlyingMatchType (using Context ): Type =
4697- if ctx.period != validUnderlyingMatch then
4698- cachedUnderlyingMatch = superType.underlyingMatchType
4699- validUnderlyingMatch = validSuper
4700- cachedUnderlyingMatch
4694+ override def underlyingNormalizable (using Context ): Type =
4695+ if ctx.period != validUnderlyingNormalizable then tycon match
4696+ case tycon : TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) =>
4697+ cachedUnderlyingNormalizable = this
4698+ validUnderlyingNormalizable = ctx.period
4699+ case _ =>
4700+ cachedUnderlyingNormalizable = superType.underlyingNormalizable
4701+ validUnderlyingNormalizable = validSuper
4702+ cachedUnderlyingNormalizable
47014703
4702- override def tryNormalize (using Context ): Type = tycon.stripTypeVar match {
4703- case tycon : TypeRef =>
4704- def tryMatchAlias = tycon.info match
4705- case AliasingBounds (alias) if isMatchAlias =>
4706- trace(i " normalize $this" , typr, show = true ) {
4707- MatchTypeTrace .recurseWith(this ) {
4708- alias.applyIfParameterized(args.map(_.normalized)).tryNormalize
4709- /* `applyIfParameterized` may reduce several HKTypeLambda applications
4710- * before the underlying MatchType is reached.
4711- * Even if they do not involve any match type normalizations yet,
4712- * we still want to record these reductions in the MatchTypeTrace.
4713- * They should however only be attempted if they eventually expand
4714- * to a match type, which is ensured by the `isMatchAlias` guard.
4715- */
4716- }
4717- }
4718- case _ =>
4719- NoType
4720- tryCompiletimeConstantFold.orElse(tryMatchAlias)
4721- case _ =>
4722- NoType
4723- }
4704+ override def tryNormalize (using Context ): Type =
4705+ if isMatchAlias && MatchTypeTrace .isRecording then
4706+ MatchTypeTrace .recurseWith(this )(superType.tryNormalize)
4707+ else super .tryNormalize
47244708
47254709 /** Is this an unreducible application to wildcard arguments?
47264710 * This is the case if tycon is higher-kinded. This means
@@ -5183,13 +5167,6 @@ object Types extends TypeUtils {
51835167 private var myReduced : Type | Null = null
51845168 private var reductionContext : util.MutableMap [Type , Type ] | Null = null
51855169
5186- override def tryNormalize (using Context ): Type =
5187- try
5188- reduced.normalized
5189- catch
5190- case ex : Throwable =>
5191- handleRecursive(" normalizing" , s " ${scrutinee.show} match ... " , ex)
5192-
51935170 private def thisMatchType = this
51945171
51955172 def reduced (using Context ): Type = atPhaseNoLater(elimOpaquePhase) {
@@ -5292,7 +5269,7 @@ object Types extends TypeUtils {
52925269 def apply (bound : Type , scrutinee : Type , cases : List [Type ])(using Context ): MatchType =
52935270 unique(new CachedMatchType (bound, scrutinee, cases))
52945271
5295- def thatReducesUsingGadt (tp : Type )(using Context ): Boolean = tp.underlyingMatchType match
5272+ def thatReducesUsingGadt (tp : Type )(using Context ): Boolean = tp.underlyingNormalizable match
52965273 case mt : MatchType => mt.reducesUsingGadt
52975274 case _ => false
52985275
@@ -5741,7 +5718,8 @@ object Types extends TypeUtils {
57415718 /** Common supertype of `TypeAlias` and `MatchAlias` */
57425719 abstract class AliasingBounds (val alias : Type ) extends TypeBounds (alias, alias) {
57435720
5744- def derivedAlias (alias : Type )(using Context ): AliasingBounds
5721+ def derivedAlias (alias : Type )(using Context ): AliasingBounds =
5722+ if alias eq this .alias then this else AliasingBounds (alias)
57455723
57465724 override def computeHash (bs : Binders ): Int = doHash(bs, alias)
57475725 override def hashIsStable : Boolean = alias.hashIsStable
@@ -5763,10 +5741,7 @@ object Types extends TypeUtils {
57635741
57645742 /** = T
57655743 */
5766- class TypeAlias (alias : Type ) extends AliasingBounds (alias) {
5767- def derivedAlias (alias : Type )(using Context ): AliasingBounds =
5768- if (alias eq this .alias) this else TypeAlias (alias)
5769- }
5744+ class TypeAlias (alias : Type ) extends AliasingBounds (alias)
57705745
57715746 /** = T where `T` is a `MatchType`
57725747 *
@@ -5775,10 +5750,7 @@ object Types extends TypeUtils {
57755750 * If we assumed full substitutivity, we would have to reject all recursive match
57765751 * aliases (or else take the jump and allow full recursive types).
57775752 */
5778- class MatchAlias (alias : Type ) extends AliasingBounds (alias) {
5779- def derivedAlias (alias : Type )(using Context ): AliasingBounds =
5780- if (alias eq this .alias) this else MatchAlias (alias)
5781- }
5753+ class MatchAlias (alias : Type ) extends AliasingBounds (alias)
57825754
57835755 object TypeBounds {
57845756 def apply (lo : Type , hi : Type )(using Context ): TypeBounds =
0 commit comments