Skip to content

Commit d2a12f1

Browse files
committed
Break looping in checkable/hasPoison
1 parent e159fa1 commit d2a12f1

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,13 @@ object TypeTestsCasts {
158158
val methodSymbol = sym.owner
159159
val tpSyms = typer.ErrorReporting.substitutableTypeSymbolsInScope(sym).toSet
160160
def isAccessible(sym: Symbol): Boolean = sym == methodSymbol || sym.isType && isAccessible(sym.owner)
161+
val seen = scala.collection.mutable.Set.empty[Type]
161162
def hasPoison(tp: Type): Boolean =
163+
seen += tp
162164
tp.baseClasses.filter(isAccessible).exists { sym =>
163165
sym.info.decls.exists { sym =>
164166
sym.info.existsPart(tp => tpSyms.contains(tp.typeSymbol))
165-
|| isAccessible(sym.info.typeSymbol.maybeOwner) && hasPoison(sym.info)
167+
|| !seen.contains(sym.info) && isAccessible(sym.info.typeSymbol.maybeOwner) && hasPoison(sym.info)
166168
}
167169
}
168170
!hasPoison(tp2)

tests/neg/i4812.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@
1818
50 | case prev: A => // error: the type test for A cannot be checked at runtime
1919
| ^
2020
| the type test for A cannot be checked at runtime
21+
-- Error: tests/neg/i4812.scala:60:11 ----------------------------------------------------------------------------------
22+
60 | case prev: Foo => // error: the type test for A cannot be checked at runtime
23+
| ^
24+
| the type test for Foo cannot be checked at runtime

tests/neg/i4812.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ object Test:
5353
prev = new A(x)
5454
x
5555

56+
def test6[T](x: T): T =
57+
class Foo { var bar: Bar = null }
58+
class Bar { var foo: Foo = null; var elem: T = _ }
59+
prev match
60+
case prev: Foo => // error: the type test for A cannot be checked at runtime
61+
prev.bar.elem
62+
case _ =>
63+
val foo = new Foo
64+
val bar = new Bar
65+
bar.elem = x
66+
foo.bar = bar
67+
prev = foo
68+
x
69+
5670
def main(args: Array[String]): Unit =
5771
test(1)
5872
val x: String = test("") // was: ClassCastException: java.lang.Integer cannot be cast to java.lang.String

0 commit comments

Comments
 (0)