Skip to content

Commit 9d12f01

Browse files
committed
Erasure#typedSelect: Handle inaccessible qualifier
Previously, the code would have gone into an infinite loop, instead we now emit an error like in Scala 2.
1 parent 5cdfd31 commit 9d12f01

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import core.Annotations.BodyAnnotation
2020
import typer.{NoChecking, LiftErased}
2121
import typer.Inliner
2222
import typer.ProtoTypes._
23+
import typer.ErrorReporting.errorTree
2324
import core.TypeErasure._
2425
import core.Decorators._
2526
import dotty.tools.dotc.ast.{tpd, untpd}
@@ -700,8 +701,17 @@ object Erasure {
700701
else
701702
val castTarget = // Avoid inaccessible cast targets, see i8661
702703
if sym.owner.isAccessibleFrom(qual1.tpe)(using preErasureCtx)
703-
then sym.owner.typeRef
704-
else erasure(tree.qualifier.typeOpt.widen)
704+
then
705+
sym.owner.typeRef
706+
else
707+
// If the owner is inaccessible, try going through the qualifier,
708+
// but be careful to not go in an infinite loop in case that doesn't
709+
// work either.
710+
val tp = erasure(tree.qualifier.typeOpt.widen)
711+
if tp =:= qual1.tpe.widen then
712+
return errorTree(qual1,
713+
ex"Unable to emit reference to ${sym.showLocated}, ${sym.owner} is not accessible in ${ctx.owner.enclosingClass}")
714+
tp
705715
recur(cast(qual1, castTarget))
706716
}
707717
}

tests/neg/java-trait-access/A.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package pkg;
2+
3+
class A {
4+
public void foo() {}
5+
}

tests/neg/java-trait-access/B.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package pkg {
2+
trait B extends A
3+
class C extends B
4+
}
5+
6+
object Test {
7+
def test1: Unit = {
8+
val c = new pkg.C
9+
c.foo() // OK
10+
val b: pkg.B = c
11+
b.foo() // error: Unable to emit reference to method foo in class A, class A is not accessible in object Test
12+
}
13+
}

0 commit comments

Comments
 (0)