diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index fe9355c55d28..4265f57851d6 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -148,7 +148,23 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { if (Config.traceDeepSubTypeRecursions && !this.isInstanceOf[ExplainingTypeComparer]) ctx.log(TypeComparer.explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2))) } - val p = (tp1, tp2) + // Eliminate LazyRefs before checking whether we have seen a type before + val normalize = new TypeMap { + val DerefLimit = 10 + var derefCount = 0 + def apply(t: Type) = t match { + case t: LazyRef => + // Dereference a lazyref to detect underlying matching types, but + // be careful not to get into an infinite recursion. If recursion count + // exceeds `DerefLimit`, approximate with `NoType` instead. + derefCount += 1 + if (derefCount >= DerefLimit) NoType + else try mapOver(t.ref) finally derefCount -= 1 + case _ => + mapOver(t) + } + } + val p = (normalize(tp1), normalize(tp2)) !pendingSubTypes(p) && { try { pendingSubTypes += p diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 480f1d3ee122..53b6d775675f 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -191,6 +191,7 @@ class CompilationTests extends ParallelTesting { compileFile("../tests/neg-custom-args/pureStatement.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("../tests/neg-custom-args/i3589-a.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("../tests/neg-custom-args/i2333.scala", defaultOptions.and("-Xfatal-warnings")) + + compileFile("../tests/neg-custom-args/i3882.scala", allowDeepSubtypes) + compileFile("../tests/neg-custom-args/phantom-overload.scala", allowDoubleBindings) + compileFile("../tests/neg-custom-args/phantom-overload-2.scala", allowDoubleBindings) + compileFile("../tests/neg-custom-args/structural.scala", defaultOptions.and("-Xfatal-warnings")) diff --git a/tests/neg-custom-args/i3882.scala b/tests/neg-custom-args/i3882.scala new file mode 100644 index 000000000000..eb28fd5632ce --- /dev/null +++ b/tests/neg-custom-args/i3882.scala @@ -0,0 +1,5 @@ +trait Ring[A <: Ring[A]] + +object Test { + def crash[T <: Ring[_ <: T]]: Ring[T] = ??? // error: Type argument T does not conform to upper bound Ring[LazyRef(T)] +}