@@ -580,50 +580,68 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
580580 *
581581 */
582582 def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
583- // map `ThisType` of `tp1` to a type variable
584- // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
585- def childTypeMap (implicit ctx : Context ) = new TypeMap {
586- def apply (t : Type ): Type = t.dealias match {
587- case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
588- if (tref.symbol.is(Module )) this (tref)
589- else newTypeVar(TypeBounds .upper(tp.underlying))
583+ // expose abstract type references to their bounds or tvars according to variance
584+ abstract class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
585+ def expose (tp : TypeRef ): Type = {
586+ val lo = this (tp.info.loBound)
587+ val hi = this (tp.info.hiBound)
588+ val exposed =
589+ if (variance == 0 )
590+ newTypeVar(TypeBounds (lo, hi))
591+ else if (variance == 1 )
592+ if (maximize) hi else lo
593+ else
594+ if (maximize) lo else hi
595+
596+ debug.println(s " $tp exposed to =====> $exposed" )
597+ exposed
598+ }
590599
600+ override def mapOver (tp : Type ): Type = tp match {
591601 case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
592- // Note that the logic for contra- and co-variance is reverse of `parentTypeMap`
593- // This is because we are checking the possibility of `tp1 <:< tp2`, thus we should
594- // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
595- val lo = tp.underlying.loBound
596- val hi = tp.underlying.hiBound
602+ // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
603+ expose(tp)
604+
605+ case AppliedType (tycon : TypeRef , args) if tycon.underlying.isInstanceOf [TypeBounds ] =>
606+ val args2 = args.map(this )
607+ val lo = this (tycon.info.loBound).applyIfParameterized(args2)
608+ val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
597609 val exposed =
598- if (variance == 0 ) newTypeVar(TypeBounds (this (lo), this (hi)))
599- else if (variance == 1 ) this (lo)
600- else this (hi)
610+ if (variance == 0 )
611+ newTypeVar(TypeBounds (lo, hi))
612+ else if (variance == 1 )
613+ if (maximize) hi else lo
614+ else
615+ if (maximize) lo else hi
616+
601617 debug.println(s " $tp exposed to =====> $exposed" )
602618 exposed
603- case tp =>
604- mapOver(tp)
619+
620+ case _ =>
621+ super .mapOver(tp)
605622 }
606623 }
607624
608- // replace type parameter references with bounds
609- def parentTypeMap (implicit ctx : Context ) = new TypeMap {
625+ // We are checking the possibility of `tp1 <:< tp2`, thus we should
626+ // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
627+ def childTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false ) {
610628 def apply (t : Type ): Type = t.dealias match {
611- case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
612- // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
613- val lo = tp.underlying.loBound
614- val hi = tp.underlying.hiBound
615- val exposed =
616- if (variance == 0 ) newTypeVar(TypeBounds (this (lo), this (hi)))
617- else if (variance == 1 ) this (hi)
618- else this (lo)
629+ // map `ThisType` of `tp1` to a type variable
630+ // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
631+ case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
632+ if (tref.symbol.is(Module )) this (tref)
633+ else newTypeVar(TypeBounds .upper(tp.underlying))
619634
620- debug.println(s " $tp exposed to =====> $exposed" )
621- exposed
622635 case tp =>
623636 mapOver(tp)
624637 }
625638 }
626639
640+ // replace type parameter references with bounds
641+ def parentTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true ) {
642+ def apply (tp : Type ): Type = mapOver(tp.dealias)
643+ }
644+
627645 // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
628646 def instUndetMap (implicit ctx : Context ) = new TypeMap {
629647 def apply (t : Type ): Type = t match {
0 commit comments