@@ -113,6 +113,7 @@ trait SpaceLogic {
113113 case Prod (tp, fun, sym, spaces, full) =>
114114 val sp = Prod (tp, fun, sym, spaces.map(simplify(_)), full)
115115 if (sp.params.contains(Empty )) Empty
116+ else if (canDecompose(tp) && decompose(tp).isEmpty) Empty
116117 else sp
117118 case Or (spaces) =>
118119 val set = spaces.map(simplify(_)).flatMap {
@@ -349,18 +350,19 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
349350 Empty
350351 }
351352
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)
364366 }
365367
366368 /** Space of the pattern: unapplySeq(a, b, c: _*)
@@ -384,7 +386,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
384386 /** Is `tp1` a subtype of `tp2`? */
385387 def isSubType (tp1 : Type , tp2 : Type ): Boolean = {
386388 val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
387- debug.println(s " ${tp1.show } <:< ${tp2.show } = $res" )
389+ debug.println(s " ${tp1} <:< ${tp2} = $res" )
388390 res
389391 }
390392
@@ -587,8 +589,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
587589 noClassConflict &&
588590 (! isSingleton(tp1) || tp1 <:< tp2) &&
589591 (! 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) )
592594 }
593595 case OrType (tp1, tp2) =>
594596 recur(tp1) || recur(tp2)
@@ -607,6 +609,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
607609 res
608610 }
609611
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+
610647 /** Instantiate type `tp1` to be a subtype of `tp2`
611648 *
612649 * Return the instantiated type if type parameters and this type
@@ -616,25 +653,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
616653 *
617654 */
618655 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-
638656 // Fix subtype checking for child instantiation,
639657 // such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
640658 // See tests/patmat/i3938.scala
0 commit comments