Skip to content

Commit 7741f12

Browse files
authored
Merge pull request #3885 from dotty-staging/fix-#3882
Fix #3882: Take LazyRefs into account for monitored subtype checking
2 parents 6e9d7c7 + 95f5273 commit 7741f12

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,23 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
148148
if (Config.traceDeepSubTypeRecursions && !this.isInstanceOf[ExplainingTypeComparer])
149149
ctx.log(TypeComparer.explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2)))
150150
}
151-
val p = (tp1, tp2)
151+
// Eliminate LazyRefs before checking whether we have seen a type before
152+
val normalize = new TypeMap {
153+
val DerefLimit = 10
154+
var derefCount = 0
155+
def apply(t: Type) = t match {
156+
case t: LazyRef =>
157+
// Dereference a lazyref to detect underlying matching types, but
158+
// be careful not to get into an infinite recursion. If recursion count
159+
// exceeds `DerefLimit`, approximate with `NoType` instead.
160+
derefCount += 1
161+
if (derefCount >= DerefLimit) NoType
162+
else try mapOver(t.ref) finally derefCount -= 1
163+
case _ =>
164+
mapOver(t)
165+
}
166+
}
167+
val p = (normalize(tp1), normalize(tp2))
152168
!pendingSubTypes(p) && {
153169
try {
154170
pendingSubTypes += p

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ class CompilationTests extends ParallelTesting {
191191
compileFile("../tests/neg-custom-args/pureStatement.scala", defaultOptions.and("-Xfatal-warnings")) +
192192
compileFile("../tests/neg-custom-args/i3589-a.scala", defaultOptions.and("-Xfatal-warnings")) +
193193
compileFile("../tests/neg-custom-args/i2333.scala", defaultOptions.and("-Xfatal-warnings")) +
194+
compileFile("../tests/neg-custom-args/i3882.scala", allowDeepSubtypes) +
194195
compileFile("../tests/neg-custom-args/phantom-overload.scala", allowDoubleBindings) +
195196
compileFile("../tests/neg-custom-args/phantom-overload-2.scala", allowDoubleBindings) +
196197
compileFile("../tests/neg-custom-args/structural.scala", defaultOptions.and("-Xfatal-warnings"))

tests/neg-custom-args/i3882.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait Ring[A <: Ring[A]]
2+
3+
object Test {
4+
def crash[T <: Ring[_ <: T]]: Ring[T] = ??? // error: Type argument T does not conform to upper bound Ring[LazyRef(T)]
5+
}

0 commit comments

Comments
 (0)