Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call on self type leads to IllegalAccessError #13007

Closed
lrytz opened this issue Jun 12, 2024 · 1 comment · Fixed by scala/scala#10794
Closed

Call on self type leads to IllegalAccessError #13007

lrytz opened this issue Jun 12, 2024 · 1 comment · Fixed by scala/scala#10794
Assignees
Milestone

Comments

@lrytz
Copy link
Member

lrytz commented Jun 12, 2024

Java:

package j;
public class J {
  protected boolean i() { return false; }
}

Scala:

package s

trait T { self: j.J =>
  override def i(): Boolean = self.i() || true;
}
class C extends j.J with T

object Test {
  def main(args: Array[String]): Unit = {
    println(new C().i())
  }
}

This crashes with IllegalAccessError: class s.T tried to access protected method j.J.i.

Before scala/scala#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.

@lrytz lrytz self-assigned this Jun 12, 2024
@som-snytt som-snytt changed the title Call on self type leads to IlleagalAccessError Call on self type leads to IllegalAccessError Jun 12, 2024
@lrytz
Copy link
Member Author

lrytz commented Jun 13, 2024

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.

    • We need to allow it if the method is defined in Scala, that's t780.scala

    • 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants