Skip to content

Commit

Permalink
Do not propagate TypeErrors of ops from TypeComparer#tryAlso
Browse files Browse the repository at this point in the history
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
  • Loading branch information
EugeneFlesselle committed Jul 6, 2024
1 parent ab48a55 commit 2d0e373
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1954,7 +1954,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
// check whether `op2` generates a weaker constraint than `op1`
val leftConstraint = constraint
constraint = preConstraint
if !(op && subsumes(leftConstraint, constraint, preConstraint)) then
val res = try op catch case _: TypeError => false
if !(res && subsumes(leftConstraint, constraint, preConstraint)) then
if constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint) then
constr.println(i"CUT - prefer $leftConstraint over $constraint")
constraint = leftConstraint
Expand Down
36 changes: 36 additions & 0 deletions tests/pos-deep-subtype/i21015.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

type Init[Coll[_], A, T <: Tuple] = T match
case EmptyTuple => A
case head *: rest => InitCons[Coll, A, head, rest]

type InitCons[Coll[_], A, H, Rest <: Tuple] = H match
case Int => Init[Coll, Coll[A], Rest]
case _ => Unit

def fillVector[A, T <: Tuple](dims: T)(x: => A): Init[Vector, A, T] =
dims match
case _: EmptyTuple => x
case (p : (head *: rest)) =>
val (head *: rest) = p
head match
case size: Int => fillVector(rest)(Vector.fill(size)(x))
case _ => ()


object Minimization:

type M1[A] = Int match
case 1 => M2[A]

type M2[A] = Int match
case 2 => M1[Option[A]]

def m1[A](x: A): M1[A] = ???

val _: M1[Int] = m1(1) // was error
val _: M1[Int] = m1[Int](1) // ok
val _: M1[Int] =
val x = m1(1)
x // ok

end Minimization

0 comments on commit 2d0e373

Please sign in to comment.