Skip to content

Commit 53ba3c8

Browse files
committed
Force LazyRef in AvoidWildcardsMap
This is to avoid unneeded new LazyRef's. LazyRefs, which are created for recursive types, aren't cacheable, so if you TypeMap an AppliedType with one, it will create a brand new instance. OrderingConstraint#init runs AvoidWildcardsMap on param bounds. So when instDirection compares the constraint bounds and the original param bounds (to calculate the instantiate direction), because they are new instances they won't shortcircuit, leading to a recursion overflow. By forcing, it will eq check and return true. In particular, with i5877, which is a neg test of recursive overflows, the new implementation of interpolateTypeVars does more type comparisons (to calculate the instDirection). If the LazyRefs are kept eq, then the AppliedTypes in the bounds are also eq, and so the subtyping check shortcircuits true, rather than overflowing.
1 parent 1d56a51 commit 53ba3c8

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -6631,6 +6631,9 @@ object Types extends TypeUtils {
66316631
range(atVariance(-variance)(apply(bounds.lo)), apply(bounds.hi))
66326632
def apply(t: Type): Type = t match
66336633
case t: WildcardType => mapWild(t)
6634+
case tp: LazyRef => mapOver(tp) match
6635+
case tp1: LazyRef if tp.ref eq tp1.ref => tp
6636+
case tp1 => tp1
66346637
case _ => mapOver(t)
66356638

66366639
// ----- TypeAccumulators ----------------------------------------------------

tests/neg-deep-subtype/i5877.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
object Main { // error // error
1+
object Main {
22
def main(a: Array[String]): Unit = {
33
println("you may not run `testHasThisType` - just check that it compiles")
44
// comment lines after "// this line of code makes" comments to make it compilable again
@@ -18,25 +18,25 @@ object Main { // error // error
1818

1919
// ---- ---- ---- ----
2020

21-
def testHasThisType(): Unit = { // error // error
21+
def testHasThisType(): Unit = {
2222
def testSelf[PThis <: HasThisType[_ <: PThis]](that: HasThisType[PThis]): Unit = {
2323
val thatSelf = that.self()
2424
// that.self().type <: that.This
2525
assert(implicitly[thatSelf.type <:< that.This] != null)
2626
}
2727
val that: HasThisType[_] = Foo() // null.asInstanceOf
28-
testSelf(that) // error: recursion limit exceeded // error
28+
testSelf(that) // error: recursion limit exceeded
2929
}
3030

3131

32-
def testHasThisType2(): Unit = { // error // error
32+
def testHasThisType2(): Unit = {
3333
def testSelf[PThis <: HasThisType[_ <: PThis]](that: PThis with HasThisType[PThis]): Unit = {
3434
// that.type <: that.This
3535
assert(implicitly[that.type <:< that.This] != null)
3636
}
3737
val that: HasThisType[_] = Foo() // null.asInstanceOf
3838
// this line of code makes Dotty compiler infinite recursion (stopped only by overflow) - comment it to make it compilable again
39-
testSelf(that) // error: recursion limit exceeded // error
39+
testSelf(that) // error: recursion limit exceeded
4040
}
4141

4242
// ---- ---- ---- ----

0 commit comments

Comments
 (0)