@@ -602,10 +602,19 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
602
602
// map `ThisType` of `tp1` to a type variable
603
603
// precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
604
604
val thisTypeMap = new TypeMap {
605
- def apply (t : Type ): Type = t match {
605
+ def apply (t : Type ): Type = t.dealias match {
606
606
case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
607
607
if (tref.symbol.is(Module )) mapOver(tref)
608
608
else newTypeVar(TypeBounds .upper(tp.underlying))
609
+ case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
610
+ // See tests/patmat/3645b.scala
611
+ val exposed =
612
+ if (variance == 0 ) newTypeVar(tp.underlying.bounds)
613
+ else if (variance == 1 ) mapOver(tp.underlying.hiBound)
614
+ else mapOver(tp.underlying.loBound)
615
+
616
+ debug.println(s " $tp exposed to =====> $exposed" )
617
+ exposed
609
618
case _ =>
610
619
mapOver(t)
611
620
}
@@ -644,13 +653,19 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
644
653
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
645
654
val protoTp1 = thisTypeMap(tp1.appliedTo(tvars))
646
655
656
+ // tests/patmat/3645b.scala
657
+ def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
658
+ (parent.argInfos.nonEmpty || parent.abstractTypeMembers.nonEmpty) &&
659
+ instantiate(parent, tp2)(ctx.fresh.setNewTyperState()).exists
660
+ }
661
+
647
662
if (protoTp1 <:< tp2) {
648
663
if (isFullyDefined(protoTp1, force)) protoTp1
649
664
else instUndetMap(protoTp1)
650
665
}
651
666
else {
652
667
val protoTp2 = typeParamMap(tp2)
653
- if (protoTp1 <:< protoTp2) {
668
+ if (protoTp1 <:< protoTp2 || parentQualify ) {
654
669
if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
655
670
else instUndetMap(protoTp1)
656
671
}
0 commit comments