@@ -599,50 +599,68 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
599
599
*
600
600
*/
601
601
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
+ }
609
618
619
+ override def mapOver (tp : Type ): Type = tp match {
610
620
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)
616
628
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
+
620
636
debug.println(s " $tp exposed to =====> $exposed" )
621
637
exposed
622
- case tp =>
623
- mapOver(tp)
638
+
639
+ case _ =>
640
+ super .mapOver(tp)
624
641
}
625
642
}
626
643
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 ) {
629
647
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))
638
653
639
- debug.println(s " $tp exposed to =====> $exposed" )
640
- exposed
641
654
case tp =>
642
655
mapOver(tp)
643
656
}
644
657
}
645
658
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
+
646
664
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
647
665
def instUndetMap (implicit ctx : Context ) = new TypeMap {
648
666
def apply (t : Type ): Type = t match {
0 commit comments