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

[24] Local instantiation in static context allowed by ECJ #3687

Closed
jarthana opened this issue Feb 5, 2025 · 5 comments
Closed

[24] Local instantiation in static context allowed by ECJ #3687

jarthana opened this issue Feb 5, 2025 · 5 comments

Comments

@jarthana
Copy link
Member

jarthana commented Feb 5, 2025

The following code that contains an instantiation of a local in a static context is allowed by the compiler. This was allowed by earlier JDK24s, but as of ea34, is rejected).

public class X {
	public void main(String[] args) {
		System.out.println(foo() != 0);
	}
	static int foo() {
		class Local {
			int value = 0;
			class Local2 {
				public static int bar() {
					return new Local().value;
				}
			}
		}
		return Local.Local2.bar();
	}
}

@stephan-herrmann I haven't yet looked at the spec, but it appears that we should be rejecting this code?

I also did some investigation and found this code to be involved (AllocationExpression, line 371:

MethodScope enclosingMethodScope = local.scope.enclosingMethodScope();

First of all, I don't think I understand the !enclosingMethodScope.isStatic in the check in line 372. The second part I don't understand is why we are ignoring the scope of the AllocationExpression itself.

@jarthana
Copy link
Member Author

jarthana commented Feb 5, 2025

Here's another related testcase where we are rejecting but Javac is accepting:

public class X {
    static int INT_FIELD = new Object() {
        class Local {
            int value = 0;
            class Local2 {
                public int bar() {
                    return new Local().value;
                }
            }
        }
    }.hashCode();
}

@stephan-herrmann
Copy link
Contributor

Thanks, @jarthana I'll go back to studying the papers 😄

@stephan-herrmann
Copy link
Contributor

stephan-herrmann commented Feb 6, 2025

Regarding the first example I see two violations, actually:

Allocation new Local():

JLS §15.9.2:

If C is an inner local class, then:

  • If C occurs in a static context, then i has no immediately enclosing instance. Let S be the nearest static method declaration, static field declaration, or static initializer that encloses the declaration of C. If the nearest static method declaration, static field declaration, or static initializer that encloses the class instance creation expression is not S, then a compile-time error occurs.
  • C = Local
  • S = X.foo()
  • "nearest static ... that encloses the class instance creation expression" = Local2.bar()
  • X.foo() != Local2.bar() => ERROR

Field access new Local().value

deleted

I was confused trying to apply a rule for simple expression name, whereas what we have is a field reference.

=> One error is enough.

@stephan-herrmann
Copy link
Contributor

While fixing this I get into a conflict with tests like org.eclipse.jdt.core.tests.compiler.regression.LocalEnumTest.test077():

public class X {
	
	public static void main(String[] args) {
		enum E {
			A {
				void bar() {
					new M();
				}
			};
			abstract void bar();
			
			class M {
				M() {
					System.out.println("SUCCESS");
				}
			}
		}
		E.A.bar();
	}
}

Hitherto a conforming test, we now start to report

	new M();
	^^^^^^^
Cannot instantiate local class 'E.M' in a static context

javac >= 16 complains similarly ("no enclosing instance"). (before 16 enums were not allowed to be local).

I think the error is correct, because the body of A is an implicit anonymous class inside the initializer of the implicit static field A. So we are in a static context indeed, where the member class M cannot be instantiated without qualification.

@jarthana @mpalat please speak up if you disagree 😄

stephan-herrmann added a commit to stephan-herrmann/eclipse.jdt.core that referenced this issue Feb 6, 2025
+ allocation must compare "nearest enclosing static scope
+ search for enclosing static should not go beyond the target enclosing
+ LocalEnumTest: corrected some expected outcomes
  + extracted subset from one test for specific comparison with javac

Fixes eclipse-jdt#3687
stephan-herrmann added a commit that referenced this issue Feb 6, 2025
+ allocation must compare "nearest enclosing static scope"
+ search for enclosing static should not go beyond the target enclosing
+ LocalEnumTest: corrected some expected outcomes
  + extracted subset from one test for specific comparison with javac

Fixes #3687
@stephan-herrmann
Copy link
Contributor

Fixed by #3699

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

No branches or pull requests

2 participants