-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8334121: Anonymous class capturing two enclosing instances fails to compile #19900
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
Conversation
👋 Welcome back mcimadamore! A progress list of the required criteria for merging this PR into |
@mcimadamore This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 47 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
@mcimadamore The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
@@ -1,7 +1,7 @@ | |||
class LocalClassTest$1 -- anon | |||
LocalClassTest$1.<init>(final this$0/*implicit*/, final j, final val$i/*synthetic*/) | |||
class LocalClassTest$1CapturingLocal$1 -- anon | |||
LocalClassTest$1CapturingLocal$1.<init>(final val$this$0/*synthetic*/, final val$val$i/*synthetic*/) | |||
LocalClassTest$1CapturingLocal$1.<init>(final this$0/*implicit*/, final val$val$i/*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.
This change is caused by the fact that we no longer need to capture the constructor parameter of where the local class occurs, but we can simply point to a different enclosing instance. Now, I notice that we seem to set ACC_MANDATED
even for enclosing instance parameters for local/anon classes. I'm not sure if this is correct, since these parameters are not, strictly speaking, mandated by the spec (which is silent when it comes to local/anon class translation). Perhaps we can rectify as a separate cleanup - but if deemed important I can also address here.
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.
Looks reasonable to me.
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.
lgtm
/integrate |
Going to push as commit 9dfcd75.
Your commit was automatically rebased without conflicts. |
@mcimadamore Pushed as commit 9dfcd75. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
This PR contains a fix for an issue when translating local/anon classes. Currently, javac assumes that a local/anon class C must have an enclosing instance whose type is the innermost enclosing class of C. But this is not always true - there are cases where the innermost enclosing instance is in early construction context, so we can't really refer to its members from the local class. Moreover, even if the innermost class was accessible, there could be cases where the enclosing instance of that innermost enclosing class is not accessible.
In other words, we cannot rely on the assumption that, given a local/anonymous class, there exist a chain of enclosing instances from the innermost to the outermost. Some chain exists, but it might not start from the innermost enclosing class, and it might have holes.
The core of the fix is the addition of a new function in
Symbol
, namelySymbol::innermostAccessibleEnclosingClass
. As the name implies, the goal of this function is to return the class symbol corresponding to the innermost enclosing type that is accessible from the symbol's class. This is used byLower
to determine the type ofthis$0
, which allows us to construct a chain of enclosing instances that skips over all the inaccessible types.I've also updated the
Symbol::hasOuterInstance
method, so that it, too, will skip over inaccessible enclosing type (and only returntrue
if some accessible enclosing type is found).This cleanup brings a lot of simplifications to
Lower.FreeVarCollector
. That class is used to compute the set of captured variables inside a local/anon class. There is a workaround in this class so that if a local/anon class occurs in a pre-construction context (where the enclosingthis
is not accessible), we say that the local/anon class captures the enclosing constructor parameter of the place where the local/anon class occurs (e.g. the enclosing'this
's enclosingthis
). This adds complexity to the code, as now the set of captured variables depends on the state ofLower
. With this PR, all that logic is now gone, andFreeVarCollector
is effectively a stateless visitor.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/19900/head:pull/19900
$ git checkout pull/19900
Update a local copy of the PR:
$ git checkout pull/19900
$ git pull https://git.openjdk.org/jdk.git pull/19900/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 19900
View PR using the GUI difftool:
$ git pr show -t 19900
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/19900.diff
Webrev
Link to Webrev Comment