Closed lrytz closed 5 months ago
What I found out:
Context.isAccessible
is true when sym.isProtected && pre.isInstanceOf[ThisType]
. But in this example we cannot cast to J
in order to access i
, that runs into an IllegalAccessError
pacakge j; public class J { protected boolean i() { return true; } } // java trait T { this: j.J => def t = this.i() }
There's history / hacks around this: https://github.com/scala/scala/blob/v2.13.14/src/compiler/scala/tools/nsc/typechecker/Contexts.scala#L999-L1010
Scala 3 rejects the above example ("illegal access to protected method"), which is correct
We can find a way to also reject it in Scala 2, but we need to be careful not to reject too much.
Also it needs to compile if C
overrides i
:
trait T { this: J => override def i() = true; def t = this.i() }
In Scala 2, the type of this
is C with T
, so this.i
resolves to J.i
due to linearization. But compilation should not fail with "illegal access to protected method". I guess this works in Scala 3 because the type of this
is C & T
.
However, we need to compile it correctly; asInstanceOf[J].j
doesn't work, as shown by OP in this ticket.
Java:
Scala:
This crashes with
IllegalAccessError: class s.T tried to access protected method j.J.i
.Before https://github.com/scala/scala/pull/8835, the compiler actually emitted a protected accessor in this example, so
self.i
was actually acting like a super call.If the two classes are in the same package, the method
J.i
is accessible. In this case the runtime behavior is actually an infinite recursion, as it should be.