@@ -599,50 +599,68 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
599599 *
600600 */
601601 def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
602- // map `ThisType` of `tp1` to a type variable
603- // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
604- def childTypeMap (implicit ctx : Context ) = new TypeMap {
605- def apply (t : Type ): Type = t.dealias match {
606- case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
607- if (tref.symbol.is(Module )) this (tref)
608- else newTypeVar(TypeBounds .upper(tp.underlying))
602+ // expose abstract type references to their bounds or tvars according to variance
603+ abstract class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
604+ def expose (tp : TypeRef ): Type = {
605+ val lo = this (tp.info.loBound)
606+ val hi = this (tp.info.hiBound)
607+ val exposed =
608+ if (variance == 0 )
609+ newTypeVar(TypeBounds (lo, hi))
610+ else if (variance == 1 )
611+ if (maximize) hi else lo
612+ else
613+ if (maximize) lo else hi
614+
615+ debug.println(s " $tp exposed to =====> $exposed" )
616+ exposed
617+ }
609618
619+ override def mapOver (tp : Type ): Type = tp match {
610620 case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
611- // Note that the logic for contra- and co-variance is reverse of `parentTypeMap`
612- // This is because we are checking the possibility of `tp1 <:< tp2`, thus we should
613- // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
614- val lo = tp.underlying.loBound
615- val hi = tp.underlying.hiBound
621+ // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
622+ expose(tp)
623+
624+ case AppliedType (tycon : TypeRef , args) if tycon.underlying.isInstanceOf [TypeBounds ] =>
625+ val args2 = args.map(this )
626+ val lo = this (tycon.info.loBound).applyIfParameterized(args2)
627+ val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
616628 val exposed =
617- if (variance == 0 ) newTypeVar(TypeBounds (this (lo), this (hi)))
618- else if (variance == 1 ) this (lo)
619- else this (hi)
629+ if (variance == 0 )
630+ newTypeVar(TypeBounds (lo, hi))
631+ else if (variance == 1 )
632+ if (maximize) hi else lo
633+ else
634+ if (maximize) lo else hi
635+
620636 debug.println(s " $tp exposed to =====> $exposed" )
621637 exposed
622- case tp =>
623- mapOver(tp)
638+
639+ case _ =>
640+ super .mapOver(tp)
624641 }
625642 }
626643
627- // replace type parameter references with bounds
628- def parentTypeMap (implicit ctx : Context ) = new TypeMap {
644+ // We are checking the possibility of `tp1 <:< tp2`, thus we should
645+ // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
646+ def childTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false ) {
629647 def apply (t : Type ): Type = t.dealias match {
630- case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
631- // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
632- val lo = tp.underlying.loBound
633- val hi = tp.underlying.hiBound
634- val exposed =
635- if (variance == 0 ) newTypeVar(TypeBounds (this (lo), this (hi)))
636- else if (variance == 1 ) this (hi)
637- else this (lo)
648+ // map `ThisType` of `tp1` to a type variable
649+ // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
650+ case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
651+ if (tref.symbol.is(Module )) this (tref)
652+ else newTypeVar(TypeBounds .upper(tp.underlying))
638653
639- debug.println(s " $tp exposed to =====> $exposed" )
640- exposed
641654 case tp =>
642655 mapOver(tp)
643656 }
644657 }
645658
659+ // replace type parameter references with bounds
660+ def parentTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true ) {
661+ def apply (tp : Type ): Type = mapOver(tp.dealias)
662+ }
663+
646664 // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
647665 def instUndetMap (implicit ctx : Context ) = new TypeMap {
648666 def apply (t : Type ): Type = t match {
0 commit comments