@@ -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
@@ -576,8 +577,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
576
577
noClassConflict &&
577
578
(! isSingleton(tp1) || tp1 <:< tp2) &&
578
579
(! isSingleton(tp2) || tp2 <:< tp1) &&
579
- (! bases1.exists(_ is Final ) || tp1 <:< tp2) &&
580
- (! bases2.exists(_ is Final ) || tp2 <:< tp1)
580
+ (! bases1.exists(_ is Final ) || tp1 <:< maxTypeMap.apply( tp2) ) &&
581
+ (! bases2.exists(_ is Final ) || tp2 <:< maxTypeMap.apply( tp1) )
581
582
}
582
583
case OrType (tp1, tp2) =>
583
584
recur(tp1) || recur(tp2)
@@ -596,6 +597,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
596
597
res
597
598
}
598
599
600
+ /** expose abstract type references to their bounds or tvars according to variance */
601
+ private class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
602
+ def expose (lo : Type , hi : Type ): Type =
603
+ if (variance == 0 )
604
+ newTypeVar(TypeBounds (lo, hi))
605
+ else if (variance == 1 )
606
+ if (maximize) hi else lo
607
+ else
608
+ if (maximize) lo else hi
609
+
610
+ def apply (tp : Type ): Type = tp match {
611
+ case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
612
+ val lo = this (tp.info.loBound)
613
+ val hi = this (tp.info.hiBound)
614
+ // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
615
+ val exposed = expose(lo, hi)
616
+ debug.println(s " $tp exposed to =====> $exposed" )
617
+ exposed
618
+
619
+ case AppliedType (tycon : TypeRef , args) if tycon.underlying.isInstanceOf [TypeBounds ] =>
620
+ val args2 = args.map(this )
621
+ val lo = this (tycon.info.loBound).applyIfParameterized(args2)
622
+ val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
623
+ val exposed = expose(lo, hi)
624
+ debug.println(s " $tp exposed to =====> $exposed" )
625
+ exposed
626
+
627
+ case _ =>
628
+ mapOver(tp)
629
+ }
630
+ }
631
+
632
+ private def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
633
+ private def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
634
+
599
635
/** Instantiate type `tp1` to be a subtype of `tp2`
600
636
*
601
637
* Return the instantiated type if type parameters and this type
@@ -605,25 +641,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
605
641
*
606
642
*/
607
643
def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
608
- // expose type param references to their bounds according to variance
609
- class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends ApproximatingTypeMap {
610
- variance = if (maximize) 1 else - 1
611
-
612
- def apply (tp : Type ): Type = tp match {
613
- case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
614
- val lo = this (tp.info.loBound)
615
- val hi = this (tp.info.hiBound)
616
- // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
617
- range(lo, hi)
618
-
619
- case _ =>
620
- mapOver(tp)
621
- }
622
- }
623
-
624
- def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
625
- def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
626
-
627
644
// Fix subtype checking for child instantiation,
628
645
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
629
646
// See tests/patmat/i3938.scala
0 commit comments