Skip to content

Commit 655851c

Browse files
committed
Simplify logic in TypeComparer
1 parent 9b73493 commit 655851c

File tree

2 files changed

+24
-28
lines changed

2 files changed

+24
-28
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -899,42 +899,27 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
899899
canWidenAbstract && acc(true, tp)
900900

901901
def tryBaseType(cls2: Symbol) =
902-
903-
def computeBase(tp1: Type): Type = tp1.widenDealias match
904-
case tp @ AndType(tp11, tp12) =>
905-
// We have to treat AndTypes specially, since the normal treatment
906-
// of `(T1 & T2).baseType(C)` combines the base types of T1 and T2 via glb
907-
// which drops any types that don't exist. That forgets possible solutions.
908-
// For instance, in i18266.scala, we get to a subgoal `R & Row[Int] <: Row[String]`
909-
// where R is an uninstantiated type variable. The base type computation
910-
// of the LHS drops the non-existing base type of R and results in
911-
// `Row[Int]`, which leads to a subtype failure since `Row[Int] <: Row[String]`
912-
// does not hold. The new strategy is to declare that the base type computation
913-
// failed since R does not have a base type, and to proceed to fourthTry instead,
914-
// where we try both sides of an AndType individually.
915-
val b1 = computeBase(tp11)
916-
val b2 = computeBase(tp12)
917-
if b1.exists && b2.exists then tp.derivedAndType(b1, b2) else NoType
918-
case _ =>
919-
nonExprBaseType(tp1, cls2).boxedIfTypeParam(tp1.typeSymbol)
920-
921-
val base = computeBase(tp1)
902+
val base = nonExprBaseType(tp1, cls2).boxedIfTypeParam(tp1.typeSymbol)
922903
if base.exists && (base ne tp1)
923904
&& (!caseLambda.exists
924905
|| widenAbstractOKFor(tp2)
925906
|| tp1.widen.underlyingClassRef(refinementOK = true).exists)
926907
then
927-
isSubType(base, tp2, if (tp1.isRef(cls2)) approx else approx.addLow)
928-
&& recordGadtUsageIf { MatchType.thatReducesUsingGadt(tp1) }
929-
|| base.isInstanceOf[AndOrType] && fourthTry
908+
if isSubType(base, tp2, if tp1.isRef(cls2) then approx else approx.addLow) then
909+
recordGadtUsageIf { MatchType.thatReducesUsingGadt(tp1) }
910+
else if tp1.widenDealias.isInstanceOf[AndType] || base.isInstanceOf[OrType] then
911+
// If tp1 is a intersection, it could be that one of the original
912+
// branches of the AndType tp1 conforms to tp2, but its base type does
913+
// not, or else that its base type for cls2 does not exist, in which case
914+
// it would not show up in `base`. In either case, we need to also fall back
915+
// to fourthTry. Test case is i18226a.scala.
930916
// If base is a disjunction, this might have come from a tp1 type that
931917
// expands to a match type. In this case, we should try to reduce the type
932918
// and compare the redux. This is done in fourthTry
933-
// If base is a conjunction, it could be that one of the original
934-
// branches of the AndType tp1 conforms to tp2, but its base type does
935-
// not. So we need to also fall back to fourthTry. Test case is i18226a.scala.
919+
fourthTry
920+
else
921+
false
936922
else fourthTry
937-
end tryBaseType
938923

939924
def fourthTry: Boolean = tp1 match {
940925
case tp1: TypeRef =>

tests/pos/intersection.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,15 @@ object Test {
4040
def fooAB1: Int = fooAB
4141
def fooBA = (??? : B with A).f
4242
def fooBA1: Int = fooBA
43-
}
43+
}
44+
45+
object Test2:
46+
class Row[+X]
47+
class A
48+
class B
49+
class C extends Row[A]
50+
class D extends Row[B]
51+
val x: C & D = ???
52+
val y: Row[A & B] = x
53+
54+

0 commit comments

Comments
 (0)