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

Regression when accessing protected Java methods #13054

Open
szeiger opened this issue Oct 30, 2024 · 4 comments
Open

Regression when accessing protected Java methods #13054

szeiger opened this issue Oct 30, 2024 · 4 comments
Milestone

Comments

@szeiger
Copy link

szeiger commented Oct 30, 2024

There are already several tickets related to Java interop with protected methods. This may have the same root cause as one of them but it seems worth reporting separately because it's a regression (which I didn't see in the other tickets) and doesn't require any casts.

Given Java source file

package foo;

public class Foo {
  protected void foo() {}
}

and a Scala source file:

package bar

import foo.Foo

trait BarMixin { self: Foo =>
  protected def foo: Unit
  def bar = foo
}

class Bar extends Foo with BarMixin

object Bar extends App {
  (new Bar).foo // 1
  (new Bar).bar // 2
}

Both call sites compile in 2.12 and 2.13. Call site 1 always fails with

[error] Exception in thread "main" java.lang.IllegalAccessError: class bar.Bar$ tried to access protected method 'void foo.Foo.foo()' (bar.Bar$ and foo.Foo are in unnamed module of loader 'app')
[error] 	at bar.Bar$.delayedEndpoint$bar$Bar$1(Bar.scala:13)
[error] 	at bar.Bar$delayedInit$body.apply(Bar.scala:12)
[error] 	at scala.Function0.apply$mcV$sp(Function0.scala:39)
[error] 	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
[error] 	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
[error] 	at scala.App.$anonfun$main$1(App.scala:76)
[error] 	at scala.App.$anonfun$main$1$adapted(App.scala:76)
[error] 	at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
[error] 	at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
[error] 	at scala.collection.AbstractIterable.foreach(Iterable.scala:919)
[error] 	at scala.App.main(App.scala:76)
[error] 	at scala.App.main$(App.scala:74)
[error] 	at bar.Bar$.main(Bar.scala:12)
[error] 	at bar.Bar.main(Bar.scala)

Call site 2 works as expected up to 2.13.6 but fails in 2.13.7 and higher:

[error] Exception in thread "main" java.lang.IllegalAccessError: class bar.BarMixin tried to access protected method 'void foo.Foo.foo()' (bar.BarMixin and foo.Foo are in unnamed module of loader 'app')
[error] 	at bar.BarMixin.bar(Bar.scala:7)
[error] 	at bar.BarMixin.bar$(Bar.scala:7)
[error] 	at bar.Bar.bar(Bar.scala:10)
[error] 	at bar.Bar$.delayedEndpoint$bar$Bar$1(Bar.scala:14)
[error] 	at bar.Bar$delayedInit$body.apply(Bar.scala:12)
[error] 	at scala.Function0.apply$mcV$sp(Function0.scala:39)
[error] 	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
[error] 	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
[error] 	at scala.App.$anonfun$main$1(App.scala:76)
[error] 	at scala.App.$anonfun$main$1$adapted(App.scala:76)
[error] 	at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
[error] 	at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
[error] 	at scala.collection.AbstractIterable.foreach(Iterable.scala:926)
[error] 	at scala.App.main(App.scala:76)
[error] 	at scala.App.main$(App.scala:74)
[error] 	at bar.Bar$.main(Bar.scala:12)
[error] 	at bar.Bar.main(Bar.scala)
@lrytz lrytz added this to the Backlog milestone Oct 31, 2024
@lrytz
Copy link
Member

lrytz commented Oct 31, 2024

This is an endless struggle.. Do you have links to the other issues you came across?

@szeiger
Copy link
Author

szeiger commented Oct 31, 2024

The candidates I looked at were #12926, #10249 , #10656 (leading to similar runtime errors) and #12589 (not a runtime error but also caused by misinterpreting Java access modifiers)

@szeiger
Copy link
Author

szeiger commented Oct 31, 2024

Most workarounds that I tried are hitting the same issue. What works is either making the Java methods public (which is what we are going to do) or adding a Scala class that extends the Java class and exposes the method under a new name (important; overriding the existing method does not help because scalac will always generate a call against the base type).

@som-snytt
Copy link

-- [E049] Reference Error: Bar.scala:8:12 ------------------------------------------------------------------------------
8 |  def bar = foo
  |            ^^^
  |            Reference to foo is ambiguous.
  |            It is both defined in trait BarMixin
  |            and inherited subsequently in trait BarMixin
  |
  | longer explanation available when compiling with `-explain`
-- [E173] Reference Error: Bar.scala:14:12 -----------------------------------------------------------------------------
14 |  (new Bar).foo // 1
   |  ^^^^^^^^^^^^^
   |method foo in class Foo cannot be accessed as a member of bar.Bar from object Bar.
   |  protected[foo] method foo can only be accessed from package foo, or class Foo in package foo or one of its subclasses.
2 errors found

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

No branches or pull requests

3 participants