@@ -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,18 @@ 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) => WildcardType (tref.underlying.bounds )
360+ case _ => mapOver(tp)
361+ }
362+ }
363+
364+ map(tp)
364365 }
365366
366367 /** Space of the pattern: unapplySeq(a, b, c: _*)
@@ -384,7 +385,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
384385 /** Is `tp1` a subtype of `tp2`? */
385386 def isSubType (tp1 : Type , tp2 : Type ): Boolean = {
386387 val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
387- debug.println(s " ${tp1.show } <:< ${tp2.show } = $res" )
388+ debug.println(s " ${tp1} <:< ${tp2} = $res" )
388389 res
389390 }
390391
@@ -576,8 +577,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
576577 noClassConflict &&
577578 (! isSingleton(tp1) || tp1 <:< tp2) &&
578579 (! 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) )
581582 }
582583 case OrType (tp1, tp2) =>
583584 recur(tp1) || recur(tp2)
@@ -596,6 +597,41 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
596597 res
597598 }
598599
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+
599635 /** Instantiate type `tp1` to be a subtype of `tp2`
600636 *
601637 * Return the instantiated type if type parameters and this type
@@ -605,25 +641,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
605641 *
606642 */
607643 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-
627644 // Fix subtype checking for child instantiation,
628645 // such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
629646 // See tests/patmat/i3938.scala
0 commit comments