@@ -456,14 +456,19 @@ object Types extends TypeUtils {
456456 /** Is this a MethodType for which the parameters will not be used? */
457457 def hasErasedParams (using Context ): Boolean = false
458458
459- /** Is this a match type or a higher-kinded abstraction of one?
460- */
461- def isMatch (using Context ): Boolean = underlyingMatchType.exists
459+ /** Is this a match type or a higher-kinded abstraction of one? */
460+ def isMatch (using Context ): Boolean = stripped match
461+ case tp : MatchType => true
462+ case tp : HKTypeLambda => tp.resType.isMatch
463+ case _ => false
464+
465+ /** Does this application expand to a match type? */
466+ def isMatchAlias (using Context ): Boolean = underlyingMatchType.exists
462467
463468 def underlyingMatchType (using Context ): Type = stripped match {
464469 case tp : MatchType => tp
465470 case tp : HKTypeLambda => tp.resType.underlyingMatchType
466- case tp : AppliedType if tp.isMatchAlias => tp.superType .underlyingMatchType
471+ case tp : AppliedType => tp.underlyingMatchType
467472 case _ => NoType
468473 }
469474
@@ -4529,6 +4534,9 @@ object Types extends TypeUtils {
45294534 private var myEvalRunId : RunId = NoRunId
45304535 private var myEvalued : Type = uninitialized
45314536
4537+ private var validUnderlyingMatch : Period = Nowhere
4538+ private var cachedUnderlyingMatch : Type = uninitialized
4539+
45324540 def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
45334541 if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
45344542 myGround > 0
@@ -4585,31 +4593,38 @@ object Types extends TypeUtils {
45854593 case nil => x
45864594 foldArgs(op(x, tycon), args)
45874595
4596+ /** Exists if the tycon is a TypeRef of an alias with an underlying match type.
4597+ * Anything else should have already been reduced in `appliedTo` by the TypeAssigner.
4598+ */
4599+ override def underlyingMatchType (using Context ): Type =
4600+ if ctx.period != validUnderlyingMatch then
4601+ validUnderlyingMatch = if tycon.isProvisional then Nowhere else ctx.period
4602+ cachedUnderlyingMatch = superType.underlyingMatchType
4603+ cachedUnderlyingMatch
4604+
45884605 override def tryNormalize (using Context ): Type = tycon.stripTypeVar match {
45894606 case tycon : TypeRef =>
4590- def tryMatchAlias = tycon.info match {
4591- case MatchAlias (alias) =>
4607+ def tryMatchAlias = tycon.info match
4608+ case AliasingBounds (alias) if isMatchAlias =>
45924609 trace(i " normalize $this" , typr, show = true ) {
45934610 MatchTypeTrace .recurseWith(this ) {
45944611 alias.applyIfParameterized(args.map(_.normalized)).tryNormalize
4612+ /* `applyIfParameterized` may reduce several HKTypeLambda applications
4613+ * before the underlying MatchType is reached.
4614+ * Even if they do not involve any match type normalizations yet,
4615+ * we still want to record these reductions in the MatchTypeTrace.
4616+ * They should however only be attempted if they eventually expand
4617+ * to a match type, which is ensured by the `isMatchAlias` guard.
4618+ */
45954619 }
45964620 }
45974621 case _ =>
45984622 NoType
4599- }
46004623 tryCompiletimeConstantFold.orElse(tryMatchAlias)
46014624 case _ =>
46024625 NoType
46034626 }
46044627
4605- /** Does this application expand to a match type? */
4606- def isMatchAlias (using Context ): Boolean = tycon.stripTypeVar match
4607- case tycon : TypeRef =>
4608- tycon.info match
4609- case _ : MatchAlias => true
4610- case _ => false
4611- case _ => false
4612-
46134628 /** Is this an unreducible application to wildcard arguments?
46144629 * This is the case if tycon is higher-kinded. This means
46154630 * it is a subtype of a hk-lambda, but not a match alias.
@@ -5137,20 +5152,9 @@ object Types extends TypeUtils {
51375152 def apply (bound : Type , scrutinee : Type , cases : List [Type ])(using Context ): MatchType =
51385153 unique(new CachedMatchType (bound, scrutinee, cases))
51395154
5140- def thatReducesUsingGadt (tp : Type )(using Context ): Boolean = tp match
5141- case MatchType .InDisguise (mt) => mt.reducesUsingGadt
5142- case mt : MatchType => mt.reducesUsingGadt
5143- case _ => false
5144-
5145- /** Extractor for match types hidden behind an AppliedType/MatchAlias. */
5146- object InDisguise :
5147- def unapply (tp : AppliedType )(using Context ): Option [MatchType ] = tp match
5148- case AppliedType (tycon : TypeRef , args) => tycon.info match
5149- case MatchAlias (alias) => alias.applyIfParameterized(args) match
5150- case mt : MatchType => Some (mt)
5151- case _ => None
5152- case _ => None
5153- case _ => None
5155+ def thatReducesUsingGadt (tp : Type )(using Context ): Boolean = tp.underlyingMatchType match
5156+ case mt : MatchType => mt.reducesUsingGadt
5157+ case _ => false
51545158 }
51555159
51565160 enum MatchTypeCasePattern :
@@ -5636,6 +5640,14 @@ object Types extends TypeUtils {
56365640 def lower (lo : Type )(using Context ): TypeBounds = apply(lo, defn.AnyType )
56375641 }
56385642
5643+ object AliasingBounds :
5644+ /** A MatchAlias if alias is a match type and a TypeAlias o.w.
5645+ * Note that aliasing a MatchAlias returns a normal TypeAlias.
5646+ */
5647+ def apply (alias : Type )(using Context ): AliasingBounds =
5648+ if alias.isMatch then MatchAlias (alias) else TypeAlias (alias)
5649+ def unapply (tp : AliasingBounds ): Option [Type ] = Some (tp.alias)
5650+
56395651 object TypeAlias {
56405652 def apply (alias : Type )(using Context ): TypeAlias = unique(new TypeAlias (alias))
56415653 def unapply (tp : TypeAlias ): Option [Type ] = Some (tp.alias)
0 commit comments