Closed
Description
Compiler version
3.0.0
Minimized code
object test {
def foo[A, B](m: B) = {
m match {
case _: A =>
m match {
case _: B => // crash with -Yno-deep-subtypes
}
}
}
}
Output
exception occurred while compiling examples/same-skolem.scala
Exception in thread "main" java.lang.AssertionError: assertion failed while compiling examples/same-skolem.scala
java.lang.AssertionError: assertion failed
at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:11)
at dotty.tools.dotc.core.TypeComparer.monitoredIsSubType$1(TypeComparer.scala:224)
at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1288)
at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:186)
at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:196)
at dotty.tools.dotc.core.TypeComparer.isSub(TypeComparer.scala:198)
// many lines
at dotty.tools.dotc.Driver.process(Driver.scala:178)
at dotty.tools.dotc.Driver.main(Driver.scala:208)
at dotty.tools.dotc.Main.main(Main.scala)
[error] Nonzero exit code returned from runner: 1
[error] (scala3-compiler / Compile / runMain) Nonzero exit code returned from runner: 1
[error] Total time: 4 s, completed May 14, 2021, 5:53:21 PM
Expectation
Should compile without crashing.
Cause
After the first pattern matching, the GADT bounds will become
B >: (?1 : A)
The (?1 : A)
here is the SkolemType
we created for pattern type in constrainSimplePatternType
.
When typing the second pattern matching, the GADT bounds will become
B >: (?1 : A) | (?2 : B)
and in ConstraintHandling#addOneBound
we will ask isSubType (?1 : A) | (?2 : B) <:< Any?
to check the narrowed bounds. Note that when we are running the subtyping check, the GADT bounds of B
have already been been updated to (?1 : A) | (?2 : B)
. Related trace on the infinite loop:
==> isSubType (?1 : A) | (?2 : B) <:< Any?
==> isSubType B <:< A? // trying to simplify the OrType
// ...
<== isSubType B <:< A = false
==> isSubType A <:< B?
==> isSubType A <:< (?1 : A) | (?2 : B)? // GADT bounds of B is used here
==> isSubType B <:< A? // trying to simplify the OrType, again
// ...
<== isSubType B <:< A = false
==> isSubType A <:< B?
==> isSubType A <:< (?1 : A) | (?2 : B)? // GADT bounds of B is used again
// more lines ... infinite loop!