-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Look up members at erasure phase for generating static forwarders #12767
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This is now green. We did a similar change in 2.12.7 (scala/scala#7469) which also broke binary compatibility in almost exactly the same way. In the case of 2.12.5, there were two static forwarders for class A[T] { def get: T = ??? }
object T extends A[String] { override def get: String = "hi" } When I compile a Java Scala 3 generates the exact same static forwarders in Interestingly, javac only sees the I think this should go ahead. It's important for some Scala libraries that provide a Java API (e.g., akka, twitter/util). |
In scala/scala#7469 you note:
But based on your last comment, this reasoning is not true in Scala 3:
So unlike in Scala 2, this change would actually break binary-compatibility in practice (and @sjrd would say this means we need to release Scala 4). You also mention that:
Did you try adding ACC_SYNTHETIC too? I don't know about ejc/intellij but javac consistently ignores ACC_SYNTHETIC methods. |
The I haven't tried |
If that works, I think that would be preferable. We made a commitment to binary-compatibility when releasing 3.0.0 and we shouldn't go back on that unless we absolutely need to. |
|
Awesome, were you able to check the behavior of eclipse or intellij with this change? |
Not yet, I'll follow up on that. |
I also tested For IntelliJ, I created a fresh Java-only project and added a directory with classfiles as dependency. IntelliJ is quite confused about the dependency if it contains Scala-3-compiled classfiles, but that has nothing to do with this PR, it's the same before and after. Compiling this class into the directory
IntelliJ doesn't see the class C It works when compiling the class with Scala 2.13. I created an IntelliJ ticket (https://youtrack.jetbrains.com/issue/SCL-19171). |
// Because additional members are generated after erasure (mixin) it's difficult to compare lists of symbols | ||
// at different phases and know which ones to mark synthetic. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given:
class A[T] { def get: T = ??? }
object T extends A[String] { override def get: String = "hi" }
If I look at what we do before this PR, I see that sortedMembersBasedOnFlags returns two get
methods, but only one of them .is(Bridge)
, can't we rely on that to know that its forwarder should be synthetic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave that a try, but
trait T { def m = 1 }
object O extends T
looking up O$
's members at the backend phase we get a method O$.d
that's marked Bridge
. Also, for
trait T { def m: Object }
object O extends T { def m: String = "" }
the lookup returns both a bridge ()Object
and the ()String
method. However, 3.0.0 doesn't generate a static accessor for the bridge in this case, so it would be quite weird to start adding a new synthetic method now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking up O$'s members at the backend phase we get a method O$.d that's marked Bridge.
Ah, that's because we mark mixin forwarders as bridge too, so we could try excluding only bridges generated at erasure.
However, 3.0.0 doesn't generate a static accessor for the bridge in this case, so it would be quite weird to start adding a new synthetic method now.
But if we only add this check in the place where the original code called addForwarder
we shouldn't end up adding more forwarders.
I've implemented this idea in #12860, let me know what you think.
Static forwarders for bridges lead to ambiguous errors in some Java compilers, and the trait setters aren't meant to be called by users. Since we can't remove them without breaking binary-compatibility, we mark them ACC_SYNTHETIC so that Java compilers will ignore them. See also the discussion in scala#12767 which implements an alternate fix. Fixes scala#12753. Co-Authored-By: Lukas Rytz <lukas.rytz@gmail.com>
Forward-ports scala/scala@b6d7e0c42c
Fixes #12753