RFR: 8194743: Compiler implementation for Statements before super() [v14]

Chen Liang liach at openjdk.org
Sat Sep 23 07:01:23 UTC 2023


On Fri, 22 Sep 2023 22:02:04 GMT, Archie Cobbs <acobbs at openjdk.org> wrote:

>> This is a first draft of a patch for JEP 447.
>> 
>> Summary of changes:
>> 
>> 1. Track when we're within a constructor "prologue" via new flag `AttrContext.ctorPrologue`
>> 1. Add checks for illegal early access to `this` in constructor prologues, and update existing checks to distinguish between static context vs. constructor prologue context
>> 1. Verify allowed placement of `super()`/`this()` calls via new method `Check.checkSuperInitCalls()`
>> 1. Remove/refactor assumptions in several places that `super()`/`this()` was always the first statement
>> 
>> The changes in `Flow.java` are an example of <span>#</span>4. `Flow.FlowAnalyzer` checks 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 containing `super()`. 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 after `super()` 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 encountering `this()`, not automatically at the beginning of those  constructors. These changes produce equivalent checks, but are compatible with the new flexibility of placement of `super()`/`this()` as well as possible future changes that could occur along these same lines.
>
> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Remove obsolete flag "constructorArgs".

I understand what you mean, since you've clarified long ago. Instead, I mean this from JEP 401:
> Local and anonymous classes may be declared, but (as in a static context) they have no enclosing instance.

Currently local classes declared in pre-construction context have an enclosing instance, and I wonder if we can make them not require enclosing instances like in a static context. Local classes declared after the super/this delegate constructor call in source code will still have an enclosing instance.

I think there are already similar rules implemented for anonymous classes before this JEP, where the anonymous `Cat$1` (printing "Running") does not require an implicit `Cat` for its constructor while `Cat$2` (printing "Meow") does after compilation:

public class Cat extends Dog {
	public Cat() {
		super(new Runnable() {
			@Override
			public void run() {
				System.out.println("Running");
			}
		});

		new Runnable() {
			public void run() {
				System.out.println("Meow");
			}
		}.run();
	}

	public static void main(String... args) {
		new Cat();
	}
}

class Dog {
	Dog(Runnable action) {
		action.run();
	}
}

-------------

PR Comment: https://git.openjdk.org/jdk/pull/13656#issuecomment-1732235419


More information about the compiler-dev mailing list