Skip to content

Commit 2d0e373

Browse files
Do not propagate TypeErrors of ops from TypeComparer#tryAlso
In pos-deep-subtype/i21015.scala:30, we ask the TypeComparer if `M1[Int] <:< M1[A]` `isMatchingApply` first tries `isSubArgs` which succeeds, but then also checks if a weaker constraint is generated by `recur(tp1.superTypeNormalized, tp2.superTypeNormalized)`. The latter throws a `RecursionOverflow` which, before the changes, bypassed the former successful check, and failed the overall subtype test. Fix #21015
1 parent ab48a55 commit 2d0e373

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -1954,7 +1954,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
19541954
// check whether `op2` generates a weaker constraint than `op1`
19551955
val leftConstraint = constraint
19561956
constraint = preConstraint
1957-
if !(op && subsumes(leftConstraint, constraint, preConstraint)) then
1957+
val res = try op catch case _: TypeError => false
1958+
if !(res && subsumes(leftConstraint, constraint, preConstraint)) then
19581959
if constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint) then
19591960
constr.println(i"CUT - prefer $leftConstraint over $constraint")
19601961
constraint = leftConstraint

tests/pos-deep-subtype/i21015.scala

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
type Init[Coll[_], A, T <: Tuple] = T match
3+
case EmptyTuple => A
4+
case head *: rest => InitCons[Coll, A, head, rest]
5+
6+
type InitCons[Coll[_], A, H, Rest <: Tuple] = H match
7+
case Int => Init[Coll, Coll[A], Rest]
8+
case _ => Unit
9+
10+
def fillVector[A, T <: Tuple](dims: T)(x: => A): Init[Vector, A, T] =
11+
dims match
12+
case _: EmptyTuple => x
13+
case (p : (head *: rest)) =>
14+
val (head *: rest) = p
15+
head match
16+
case size: Int => fillVector(rest)(Vector.fill(size)(x))
17+
case _ => ()
18+
19+
20+
object Minimization:
21+
22+
type M1[A] = Int match
23+
case 1 => M2[A]
24+
25+
type M2[A] = Int match
26+
case 2 => M1[Option[A]]
27+
28+
def m1[A](x: A): M1[A] = ???
29+
30+
val _: M1[Int] = m1(1) // was error
31+
val _: M1[Int] = m1[Int](1) // ok
32+
val _: M1[Int] =
33+
val x = m1(1)
34+
x // ok
35+
36+
end Minimization

0 commit comments

Comments
 (0)