Mixin forwarders can illegally access package-private methods
package p
package u {
trait T {
private[u] def f = 1
}
}
package v {
class C extends u.T
}
generates, after mixin:
[[syntax trees at end of mixin]] // Test.scala
package p {
...
package v {
class C extends Object with p.u.T {
private[u] def f(): Int = C.super.f();
private[u] is wrong (u is not in scope), and C.super.f is an illegal access. So this code should be rejected.
This doesn't result in invalid bytecode, everything will be public anyway.
In fact, enforcing this would be wrong, we don't want to disallow extending T outside u just because it has a private[u] member.
In bytecode, the mixin method in C actually calls the compiler-generated static method T.f$ (invokestatic, no invokespecial to the private[u] method in T).
So this the issue here is purely cosmetic
- the mixin forwarder should be
public(private[u]is weird asuis not in scope) - we cannot really create a better AST than
C.super.f(), because the staticf$method is only created during code generation, there's no symbol for it
In bytecode, the mixin method in
Cactually calls the compiler-generated static methodT.f$(invokestatic, noinvokespecialto theprivate[u]method inT).
Can we make private[u] def f() public directly? I have tried it, and It seems wrong when emitting. 😄