Skip to content

Commit 94ecc05

Browse files
committed
Change order of operations in lub
Try to drop a supertype defore distributing into Or. Fixes #12286 where a type variable was not instantiated to an OrType but was distributed into the constituents instead.
1 parent aadc10f commit 94ecc05

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

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

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,43 +1934,40 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
19341934
else if (!tp2.exists) tp1
19351935
else if tp1.isAny && !tp2.isLambdaSub || tp1.isAnyKind || isBottom(tp2) then tp2
19361936
else if tp2.isAny && !tp1.isLambdaSub || tp2.isAnyKind || isBottom(tp1) then tp1
1937-
else tp2 match { // normalize to disjunctive normal form if possible.
1937+
else tp2 match
19381938
case tp2: LazyRef =>
19391939
glb(tp1, tp2.ref)
1940-
case OrType(tp21, tp22) =>
1941-
tp1 & tp21 | tp1 & tp22
19421940
case _ =>
1943-
tp1 match {
1941+
tp1 match
19441942
case tp1: LazyRef =>
19451943
glb(tp1.ref, tp2)
1946-
case OrType(tp11, tp12) =>
1947-
tp11 & tp2 | tp12 & tp2
19481944
case _ =>
19491945
val tp1a = dropIfSuper(tp1, tp2)
1950-
if (tp1a ne tp1) glb(tp1a, tp2)
1951-
else {
1946+
if tp1a ne tp1 then glb(tp1a, tp2)
1947+
else
19521948
val tp2a = dropIfSuper(tp2, tp1)
1953-
if (tp2a ne tp2) glb(tp1, tp2a)
1954-
else tp1 match {
1955-
case tp1: ConstantType =>
1956-
tp2 match {
1957-
case tp2: ConstantType =>
1958-
// Make use of the fact that the intersection of two constant types
1959-
// types which are not subtypes of each other is known to be empty.
1960-
// Note: The same does not apply to singleton types in general.
1961-
// E.g. we could have a pattern match against `x.type & y.type`
1962-
// which might succeed if `x` and `y` happen to be the same ref
1963-
// at run time. It would not work to replace that with `Nothing`.
1964-
// However, maybe we can still apply the replacement to
1965-
// types which are not explicitly written.
1966-
NothingType
1949+
if tp2a ne tp2 then glb(tp1, tp2a)
1950+
else tp2 match // normalize to disjunctive normal form if possible.
1951+
case OrType(tp21, tp22) =>
1952+
tp1 & tp21 | tp1 & tp22
1953+
case _ =>
1954+
tp1 match
1955+
case OrType(tp11, tp12) =>
1956+
tp11 & tp2 | tp12 & tp2
1957+
case tp1: ConstantType =>
1958+
tp2 match
1959+
case tp2: ConstantType =>
1960+
// Make use of the fact that the intersection of two constant types
1961+
// types which are not subtypes of each other is known to be empty.
1962+
// Note: The same does not apply to singleton types in general.
1963+
// E.g. we could have a pattern match against `x.type & y.type`
1964+
// which might succeed if `x` and `y` happen to be the same ref
1965+
// at run time. It would not work to replace that with `Nothing`.
1966+
// However, maybe we can still apply the replacement to
1967+
// types which are not explicitly written.
1968+
NothingType
1969+
case _ => andType(tp1, tp2)
19671970
case _ => andType(tp1, tp2)
1968-
}
1969-
case _ => andType(tp1, tp2)
1970-
}
1971-
}
1972-
}
1973-
}
19741971
}
19751972

19761973
def widenInUnions(using Context): Boolean =

tests/pos/i12286.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sealed trait Base { def str: String }
2+
case class One(str: String) extends Base
3+
case class Two(str: String) extends Base
4+
case class Three(str: String) extends Base
5+
6+
case class Item(_id: String)
7+
8+
private def doWithItem[T <: (One | Two | Three)]
9+
(item: Item, value: T, action: (T) => Item) = doWithItemId(item._id, value, action)
10+
private def doWithItemId[U <: (One | Two | Three)]
11+
(itemId: String, value: U, action: (U) => Item) =
12+
println(value.str)
13+
Item("_id")

0 commit comments

Comments
 (0)