@@ -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,19 @@ 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) =>
360
+ tref.underlying.bounds
361
+ case _ => mapOver(tp)
362
+ }
363
+ }
364
+
365
+ map(tp)
364
366
}
365
367
366
368
/** Space of the pattern: unapplySeq(a, b, c: _*)
@@ -384,7 +386,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
384
386
/** Is `tp1` a subtype of `tp2`? */
385
387
def isSubType (tp1 : Type , tp2 : Type ): Boolean = {
386
388
val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
387
- debug.println(s " ${tp1.show } <:< ${tp2.show } = $res" )
389
+ debug.println(s " ${tp1} <:< ${tp2} = $res" )
388
390
res
389
391
}
390
392
@@ -587,8 +589,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
587
589
noClassConflict &&
588
590
(! isSingleton(tp1) || tp1 <:< tp2) &&
589
591
(! isSingleton(tp2) || tp2 <:< tp1) &&
590
- (! bases1.exists(_ is Final ) || tp1 <:< tp2) &&
591
- (! bases2.exists(_ is Final ) || tp2 <:< tp1)
592
+ (! bases1.exists(_ is Final ) || tp1 <:< maxTypeMap.apply( tp2) ) &&
593
+ (! bases2.exists(_ is Final ) || tp2 <:< maxTypeMap.apply( tp1) )
592
594
}
593
595
case OrType (tp1, tp2) =>
594
596
recur(tp1) || recur(tp2)
@@ -607,6 +609,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
607
609
res
608
610
}
609
611
612
+ /** expose abstract type references to their bounds or tvars according to variance */
613
+ private class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
614
+ def expose (lo : Type , hi : Type ): Type =
615
+ if (variance == 0 )
616
+ newTypeVar(TypeBounds (lo, hi))
617
+ else if (variance == 1 )
618
+ if (maximize) hi else lo
619
+ else
620
+ if (maximize) lo else hi
621
+
622
+ def apply (tp : Type ): Type = tp match {
623
+ case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
624
+ val lo = this (tp.info.loBound)
625
+ val hi = this (tp.info.hiBound)
626
+ // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
627
+ val exposed = expose(lo, hi)
628
+ debug.println(s " $tp exposed to =====> $exposed" )
629
+ exposed
630
+
631
+ case AppliedType (tycon : TypeRef , args) if tycon.underlying.isInstanceOf [TypeBounds ] =>
632
+ val args2 = args.map(this )
633
+ val lo = this (tycon.info.loBound).applyIfParameterized(args2)
634
+ val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
635
+ val exposed = expose(lo, hi)
636
+ debug.println(s " $tp exposed to =====> $exposed" )
637
+ exposed
638
+
639
+ case _ =>
640
+ mapOver(tp)
641
+ }
642
+ }
643
+
644
+ private def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
645
+ private def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
646
+
610
647
/** Instantiate type `tp1` to be a subtype of `tp2`
611
648
*
612
649
* Return the instantiated type if type parameters and this type
@@ -616,25 +653,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
616
653
*
617
654
*/
618
655
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
656
// Fix subtype checking for child instantiation,
639
657
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
640
658
// See tests/patmat/i3938.scala
0 commit comments