@@ -113,6 +113,7 @@ trait SpaceLogic {
113
113
case Prod (tp, fun, sym, spaces, full) =>
114
114
val sp = Prod (tp, fun, sym, spaces.map(simplify(_)), full)
115
115
if (sp.params.contains(Empty )) Empty
116
+ else if (canDecompose(tp) && decompose(tp).isEmpty) Empty
116
117
else sp
117
118
case Or (spaces) =>
118
119
val set = spaces.map(simplify(_)).flatMap {
@@ -349,18 +350,18 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
349
350
Empty
350
351
}
351
352
352
- /* Erase a type binding according to erasure semantics in pattern matching */
353
- def erase (tp : Type ): Type = tp match {
354
- case tp @ AppliedType (tycon, args ) =>
355
- if (tycon.isRef(defn. ArrayClass )) tp.derivedAppliedType(tycon, args.map(erase))
356
- else tp.derivedAppliedType(tycon, args. map(t => WildcardType ))
357
- case OrType (tp1, tp2 ) =>
358
- OrType (erase(tp1), erase(tp2) )
359
- case AndType (tp1, tp2) =>
360
- AndType (erase(tp1), erase(tp2))
361
- case tp @ RefinedType (parent, refinedName, _) if refinedName.isTermName => // see pos/dependent-extractors.scala
362
- tp.derivedRefinedType(erase(parent), refinedName, WildcardType )
363
- case _ => tp
353
+ /* Erase pattern bound types with WildcardType */
354
+ def erase (tp : Type ) = {
355
+ def isPatternTypeSymbol ( sym : Symbol ) = ! sym.isClass && sym.is( Case )
356
+
357
+ val map = new TypeMap {
358
+ def apply ( tp : Type ) = tp match {
359
+ case tref : TypeRef if isPatternTypeSymbol(tref.typeSymbol) => WildcardType (tref.underlying.bounds )
360
+ case _ => mapOver(tp)
361
+ }
362
+ }
363
+
364
+ map(tp)
364
365
}
365
366
366
367
/** Space of the pattern: unapplySeq(a, b, c: _*)
@@ -384,7 +385,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
384
385
/** Is `tp1` a subtype of `tp2`? */
385
386
def isSubType (tp1 : Type , tp2 : Type ): Boolean = {
386
387
val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
387
- debug.println(s " ${tp1.show } <:< ${tp2.show } = $res" )
388
+ debug.println(s " ${tp1} <:< ${tp2} = $res" )
388
389
res
389
390
}
390
391
@@ -587,8 +588,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
587
588
noClassConflict &&
588
589
(! isSingleton(tp1) || tp1 <:< tp2) &&
589
590
(! isSingleton(tp2) || tp2 <:< tp1) &&
590
- (! bases1.exists(_ is Final ) || tp1 <:< tp2) &&
591
- (! bases2.exists(_ is Final ) || tp2 <:< tp1)
591
+ (! bases1.exists(_ is Final ) || tp1 <:< maxTypeMap.apply( tp2) ) &&
592
+ (! bases2.exists(_ is Final ) || tp2 <:< maxTypeMap.apply( tp1) )
592
593
}
593
594
case OrType (tp1, tp2) =>
594
595
recur(tp1) || recur(tp2)
@@ -607,6 +608,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
607
608
res
608
609
}
609
610
611
+ /** expose abstract type references to their bounds or tvars according to variance */
612
+ private class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
613
+ def expose (lo : Type , hi : Type ): Type =
614
+ if (variance == 0 )
615
+ newTypeVar(TypeBounds (lo, hi))
616
+ else if (variance == 1 )
617
+ if (maximize) hi else lo
618
+ else
619
+ if (maximize) lo else hi
620
+
621
+ def apply (tp : Type ): Type = tp match {
622
+ case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
623
+ val lo = this (tp.info.loBound)
624
+ val hi = this (tp.info.hiBound)
625
+ // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
626
+ val exposed = expose(lo, hi)
627
+ debug.println(s " $tp exposed to =====> $exposed" )
628
+ exposed
629
+
630
+ case AppliedType (tycon : TypeRef , args) if tycon.underlying.isInstanceOf [TypeBounds ] =>
631
+ val args2 = args.map(this )
632
+ val lo = this (tycon.info.loBound).applyIfParameterized(args2)
633
+ val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
634
+ val exposed = expose(lo, hi)
635
+ debug.println(s " $tp exposed to =====> $exposed" )
636
+ exposed
637
+
638
+ case _ =>
639
+ mapOver(tp)
640
+ }
641
+ }
642
+
643
+ private def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
644
+ private def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
645
+
610
646
/** Instantiate type `tp1` to be a subtype of `tp2`
611
647
*
612
648
* Return the instantiated type if type parameters and this type
@@ -616,25 +652,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
616
652
*
617
653
*/
618
654
def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
619
- // expose type param references to their bounds according to variance
620
- class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends ApproximatingTypeMap {
621
- variance = if (maximize) 1 else - 1
622
-
623
- def apply (tp : Type ): Type = tp match {
624
- case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
625
- val lo = this (tp.info.loBound)
626
- val hi = this (tp.info.hiBound)
627
- // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
628
- range(lo, hi)
629
-
630
- case _ =>
631
- mapOver(tp)
632
- }
633
- }
634
-
635
- def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
636
- def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
637
-
638
655
// Fix subtype checking for child instantiation,
639
656
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
640
657
// See tests/patmat/i3938.scala
0 commit comments