@@ -456,14 +456,19 @@ object Types extends TypeUtils {
456
456
/** Is this a MethodType for which the parameters will not be used? */
457
457
def hasErasedParams (using Context ): Boolean = false
458
458
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
462
467
463
468
def underlyingMatchType (using Context ): Type = stripped match {
464
469
case tp : MatchType => tp
465
470
case tp : HKTypeLambda => tp.resType.underlyingMatchType
466
- case tp : AppliedType if tp.isMatchAlias => tp.superType .underlyingMatchType
471
+ case tp : AppliedType => tp.underlyingMatchType
467
472
case _ => NoType
468
473
}
469
474
@@ -4529,6 +4534,9 @@ object Types extends TypeUtils {
4529
4534
private var myEvalRunId : RunId = NoRunId
4530
4535
private var myEvalued : Type = uninitialized
4531
4536
4537
+ private var validUnderlyingMatch : Period = Nowhere
4538
+ private var cachedUnderlyingMatch : Type = uninitialized
4539
+
4532
4540
def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
4533
4541
if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
4534
4542
myGround > 0
@@ -4585,31 +4593,38 @@ object Types extends TypeUtils {
4585
4593
case nil => x
4586
4594
foldArgs(op(x, tycon), args)
4587
4595
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
+
4588
4605
override def tryNormalize (using Context ): Type = tycon.stripTypeVar match {
4589
4606
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 =>
4592
4609
trace(i " normalize $this" , typr, show = true ) {
4593
4610
MatchTypeTrace .recurseWith(this ) {
4594
4611
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
+ */
4595
4619
}
4596
4620
}
4597
4621
case _ =>
4598
4622
NoType
4599
- }
4600
4623
tryCompiletimeConstantFold.orElse(tryMatchAlias)
4601
4624
case _ =>
4602
4625
NoType
4603
4626
}
4604
4627
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
-
4613
4628
/** Is this an unreducible application to wildcard arguments?
4614
4629
* This is the case if tycon is higher-kinded. This means
4615
4630
* it is a subtype of a hk-lambda, but not a match alias.
@@ -5137,20 +5152,9 @@ object Types extends TypeUtils {
5137
5152
def apply (bound : Type , scrutinee : Type , cases : List [Type ])(using Context ): MatchType =
5138
5153
unique(new CachedMatchType (bound, scrutinee, cases))
5139
5154
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
5154
5158
}
5155
5159
5156
5160
enum MatchTypeCasePattern :
@@ -5636,6 +5640,14 @@ object Types extends TypeUtils {
5636
5640
def lower (lo : Type )(using Context ): TypeBounds = apply(lo, defn.AnyType )
5637
5641
}
5638
5642
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
+
5639
5651
object TypeAlias {
5640
5652
def apply (alias : Type )(using Context ): TypeAlias = unique(new TypeAlias (alias))
5641
5653
def unapply (tp : TypeAlias ): Option [Type ] = Some (tp.alias)
0 commit comments