-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8194743: Compiler implementation for Statements before super() #13656
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 acobbs! A progress list of the required criteria for merging this PR into |
|
@archiecobbs The following labels 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 lists. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
Outdated
Show resolved
Hide resolved
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
Outdated
Show resolved
Hide resolved
Thanks to Jim Laskey for help with preview logic.
|
Mailing list message from Jim Laskey on compiler-dev: Don?t forget to update the tests to use the @enablePreview flag. ? |
|
Quick question, since I don't know much about javac, I wonder what happens if you declare a local class or an anonymous class in the ctor prologue? Will that local/anonymous class have a mandated outer instance parameter in its constructor, and thus having access to a newly allocated but non-initialized object via |
You can declare such a class in the prologue, but you can't instantiate it there: public static class LocalTest {
public LocalTest() {
class Foo {
Foo() {
LocalTest.this.hashCode();
}
}
new Foo(); // ILLEGAL
super();
new Foo(); // ALLOWED
}
} Note that:
So if we "backport" your question to JDK 20, you get the current behavior: import java.util.concurrent.atomic.*;
public class LocalTest extends AtomicReference<Object> {
public class Inner {
}
public LocalTest(int x) {
super(new Inner()); // ILLEGAL
}
public LocalTest(char x) {
super(null);
new Inner(); // ALLOWED
}
} |
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
Outdated
Show resolved
Hide resolved
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
Outdated
Show resolved
Hide resolved
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
Outdated
Show resolved
Hide resolved
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.
Overall, this is a very good patch. Not only it adds a new feature (which I found myself reaching for several times), but it also does so by consolidating a bunch of logic in the compiler code. Well done!
|
Mailing list message from Alex Buckley on compiler-dev: Hi Archie, Anything concerning the science of when nested classes have enclosing On 9/23/2023 8:19 AM, Archie Cobbs wrote:
JLS 15.9.2 says what happens when an inner local class is instantiated,
I don't see this explicit goal stated in JEP 447. There's a sentence If 100% class file compatibility for all existing source code is a goal,
I'm not, per se, disagreeing with specifying that local classes declared public class Test { public Test() { Don't worry about JEP 401 until JEP 447 has thoroughly clarified the Alex |
|
Mailing list message from Archie Cobbs on compiler-dev: Hi Alex,
You're right.. the stated goal is actually "Do not change the behavior of Making sure the emitted bytecode matches is just one way to accomplish that
Agreed.
Yes.. and same thing for non-static member classes, so this is not special Don't worry about JEP 401 until JEP 447 has thoroughly clarified the
Thanks - so yes that central question remains... how should we treat local The current implementation answers this question "they are inner classes Admittedly that answer was chosen in part because it is the most But OK let's be a little bolder and ask what would be the BEST change? My latest thinking is we should just allow local classes to be declared Then "class Local" gives the current behavior (always having an outer You could then declare AND instantiate a static local class in a Plus, this simplifies a developer's mental model for the various types of This would be the best of both worlds... ? Here's a program that tries to instantiate a Local which observes x with
JLS says this()/super() have to be "top level", so they can't be inside a try
Test.java:10: error: switch expression does not have any result expressions (The first error can be worked around by inserting case 1 -> 2; of course). -Archie -- |
|
Mailing list message from Alex Buckley on compiler-dev: On 9/25/2023 10:13 AM, Archie Cobbs wrote:
Goals: (always the hardest single section of a JEP to write, BTW) - Re: "In constructors, allow statements that do not access ..." -- this - Drop "Correct an error in the specification which defines constructor - Re: "Preserve existing safety and initialization guarantees for - Re: "Do not change the behavior of any existing program." -- stated
This is a big language change that I'm not going to comment on. You
Oops, yes. So, can you guarantee, in the JEP, that a non-static local Alex |
|
Mailing list message from Archie Cobbs on compiler-dev: Hi Alex, Thanks for the JEP comments, I will get with Gavin (who is managing the On Mon, Sep 25, 2023 at 1:25?PM Alex Buckley <alex.buckley at oracle.com>
Reading that literally, no that's not guaranteed at all. You are allowed to What you can't do is instantiate it before super(). That's enforced by this
Note this language applies to both local classes and member classes. -Archie -- |
|
/integrate |
|
@archiecobbs |
|
/sponsor |
|
Going to push as commit 12e983a.
Your commit was automatically rebased without conflicts. |
|
@vicente-romero-oracle @archiecobbs Pushed as commit 12e983a. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
This is a first draft of a patch for JEP 447.
Summary of changes:
AttrContext.ctorProloguethisin constructor prologues, and update existing checks to distinguish between static context vs. constructor prologue contextsuper()/this()calls via new methodCheck.checkSuperInitCalls()super()/this()was always the first statementThe changes in
Flow.javaare an example of #4.Flow.FlowAnalyzerchecks for uncaught checked exceptions. For initializer blocks, this was previously done by requiring that any checked exceptions thrown be declared as thrown by all constructors containingsuper(). This list of checked exceptions was being pre-calculated before recursing into the initial constructors. This worked because initializer blocks were executed at the beginning of each initial constructor right aftersuper()is called.Now initializer blocks are traversed as each
super()invocation is encountered, reflecting what actually happens at runtime. Similarly, final fields are marked as DA after encounteringthis(), not automatically at the beginning of those constructors. These changes produce equivalent checks, but are compatible with the new flexibility of placement ofsuper()/this()as well as possible future changes that could occur along these same lines.Progress
Issues
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/13656/head:pull/13656$ git checkout pull/13656Update a local copy of the PR:
$ git checkout pull/13656$ git pull https://git.openjdk.org/jdk.git pull/13656/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 13656View PR using the GUI difftool:
$ git pr show -t 13656Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/13656.diff
Webrev
Link to Webrev Comment