@@ -580,50 +580,68 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
580
580
*
581
581
*/
582
582
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
+ }
590
599
600
+ override def mapOver (tp : Type ): Type = tp match {
591
601
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)
597
609
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
+
601
617
debug.println(s " $tp exposed to =====> $exposed" )
602
618
exposed
603
- case tp =>
604
- mapOver(tp)
619
+
620
+ case _ =>
621
+ super .mapOver(tp)
605
622
}
606
623
}
607
624
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 ) {
610
628
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))
619
634
620
- debug.println(s " $tp exposed to =====> $exposed" )
621
- exposed
622
635
case tp =>
623
636
mapOver(tp)
624
637
}
625
638
}
626
639
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
+
627
645
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
628
646
def instUndetMap (implicit ctx : Context ) = new TypeMap {
629
647
def apply (t : Type ): Type = t match {
0 commit comments