@@ -10,7 +10,7 @@ import TypeOps.refineUsingParent
10
10
import collection .mutable
11
11
import util .{Stats , NoSourcePosition , EqHashMap }
12
12
import config .Config
13
- import config .Feature .{migrateTo3 , sourceVersion }
13
+ import config .Feature .{betterMatchTypeExtractorsEnabled , migrateTo3 , sourceVersion }
14
14
import config .Printers .{subtyping , gadts , matchTypes , noPrinter }
15
15
import config .SourceVersion
16
16
import TypeErasure .{erasedLub , erasedGlb }
@@ -3518,20 +3518,77 @@ class MatchReducer(initctx: Context) extends TypeComparer(initctx) {
3518
3518
false
3519
3519
3520
3520
case MatchTypeCasePattern .TypeMemberExtractor (typeMemberName, capture) =>
3521
+ /** Try to remove references to `skolem` from a type in accordance with the spec.
3522
+ *
3523
+ * If `betterMatchTypeExtractorsEnabled` is enabled then references
3524
+ * to `skolem` occuring are avoided by following aliases and
3525
+ * singletons, otherwise no attempt made to avoid references to
3526
+ * `skolem`.
3527
+ *
3528
+ * If any reference to `skolem` remains in the result type,
3529
+ * `refersToSkolem` is set to true.
3530
+ */
3531
+ class DropSkolemMap (skolem : SkolemType ) extends TypeMap :
3532
+ var refersToSkolem = false
3533
+ def apply (tp : Type ): Type =
3534
+ if refersToSkolem then
3535
+ return tp
3536
+ tp match
3537
+ case `skolem` =>
3538
+ refersToSkolem = true
3539
+ tp
3540
+ case tp : NamedType if betterMatchTypeExtractorsEnabled =>
3541
+ val pre1 = apply(tp.prefix)
3542
+ if refersToSkolem then
3543
+ tp match
3544
+ case tp : TermRef => tp.info.widenExpr.dealias match
3545
+ case info : SingletonType =>
3546
+ refersToSkolem = false
3547
+ apply(info)
3548
+ case _ =>
3549
+ tp.derivedSelect(pre1)
3550
+ case tp : TypeRef => tp.info match
3551
+ case info : AliasingBounds =>
3552
+ refersToSkolem = false
3553
+ apply(info.alias)
3554
+ case _ =>
3555
+ tp.derivedSelect(pre1)
3556
+ else
3557
+ tp.derivedSelect(pre1)
3558
+ case tp : LazyRef if betterMatchTypeExtractorsEnabled =>
3559
+ // By default, TypeMap maps LazyRefs lazily. We need to
3560
+ // force it for `refersToSkolem` to be correctly set.
3561
+ apply(tp.ref)
3562
+ case _ =>
3563
+ mapOver(tp)
3564
+ end DropSkolemMap
3565
+ /** Try to remove references to `skolem` from `u` in accordance with the spec.
3566
+ *
3567
+ * If any reference to `skolem` remains in the result type, return
3568
+ * NoType instead.
3569
+ */
3570
+ def dropSkolem (u : Type , skolem : SkolemType ): Type =
3571
+ val dmap = DropSkolemMap (skolem)
3572
+ val res = dmap(u)
3573
+ if dmap.refersToSkolem then NoType else res
3574
+
3521
3575
val stableScrut : SingletonType = scrut match
3522
3576
case scrut : SingletonType => scrut
3523
3577
case _ => SkolemType (scrut)
3578
+
3524
3579
stableScrut.member(typeMemberName) match
3525
3580
case denot : SingleDenotation if denot.exists =>
3526
3581
val info = denot.info match
3527
3582
case alias : AliasingBounds => alias.alias // Extract the alias
3528
3583
case ClassInfo (prefix, cls, _, _, _) => prefix.select(cls) // Re-select the class from the prefix
3529
3584
case info => info // Notably, RealTypeBounds, which will eventually give a MatchResult.NoInstances
3530
- val infoRefersToSkolem = stableScrut.isInstanceOf [SkolemType ] && stableScrut.occursIn(info)
3531
- val info1 = info match
3532
- case info : TypeBounds => info // Will already trigger a MatchResult.NoInstances
3533
- case _ if infoRefersToSkolem => RealTypeBounds (info, info) // Explicitly trigger a MatchResult.NoInstances
3534
- case _ => info // We have a match
3585
+ val info1 = stableScrut match
3586
+ case skolem : SkolemType =>
3587
+ dropSkolem(info, skolem).orElse:
3588
+ info match
3589
+ case info : TypeBounds => info // Will already trigger a MatchResult.NoInstances
3590
+ case _ => RealTypeBounds (info, info) // Explicitly trigger a MatchResult.NoInstances
3591
+ case _ => info
3535
3592
rec(capture, info1, variance = 0 , scrutIsWidenedAbstract)
3536
3593
case _ =>
3537
3594
false
0 commit comments