diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 2b5e6303b789..8eb53c8ef739 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -158,11 +158,13 @@ object TypeTestsCasts { val methodSymbol = sym.owner val tpSyms = typer.ErrorReporting.substitutableTypeSymbolsInScope(sym).toSet def isAccessible(sym: Symbol): Boolean = sym == methodSymbol || sym.isType && isAccessible(sym.owner) + val seen = scala.collection.mutable.Set.empty[Type] def hasPoison(tp: Type): Boolean = + seen += tp tp.baseClasses.filter(isAccessible).exists { sym => sym.info.decls.exists { sym => sym.info.existsPart(tp => tpSyms.contains(tp.typeSymbol)) - || isAccessible(sym.info.typeSymbol.maybeOwner) && hasPoison(sym.info) + || !seen.contains(sym.info) && isAccessible(sym.info.typeSymbol.maybeOwner) && hasPoison(sym.info) } } !hasPoison(tp2) diff --git a/tests/neg/i4812.scala b/tests/neg/i4812.scala index 4bf0848aa5d9..445291fbaf69 100644 --- a/tests/neg/i4812.scala +++ b/tests/neg/i4812.scala @@ -53,6 +53,20 @@ object Test: prev = new A(x) x + def test6[T](x: T): T = + class Foo { var bar: Bar = null } + class Bar { var foo: Foo = null; var elem: T = _ } + prev match + case prev: Foo => // error: the type test for A cannot be checked at runtime + prev.bar.elem + case _ => + val foo = new Foo + val bar = new Bar + bar.elem = x + foo.bar = bar + prev = foo + x + def main(args: Array[String]): Unit = test(1) val x: String = test("") // was: ClassCastException: java.lang.Integer cannot be cast to java.lang.String