eclipse-jdt / eclipse-jdt/eclipse.jdt.core

[22] Byte code backward compatibility for compilation targets < 22 violated with '-proceedOnError', because parser falsely identifies unnamed class

Open
#2,205 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
237
Forks
195
Avg merge
1d 12h
Merged PRs (30d)
47

Description

Relates to #1640.

Consider this code with a syntax error:

```java
blahblahpackage pack;

public class C {
public static void main(String[] argv) {}
}
```

```java
public class Invoker {
public static void main(String[] args) throws Throwable {
try {
C.main(null);
}
catch (Throwable t) {
boolean failedCorrectly = t.toString().indexOf("Unresolved compilation") != -1;
if (failedCorrectly)
return;
throw new RuntimeException("Call to main should have failed!", t);
}
}
}
```

Now compile with ECJ 3.36.0 and `-8 -proceedOnError` (I also tried with `-1.5`) to cause the compiler to render error messages into the byte code:

```text
$ java -jar ecj-3.36.0.jar -8 -proceedOnError Invoker.java C.java
----------
1. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\C.java (at line 1)
blahblahpackage pack;
^^^^^^^^^^^^^^^
Syntax error on token "blahblahpackage", package expected
----------
1 problem (1 error)

alexa@Xander-UB MINGW64 ~/Documents/java-src/AspectJ/tests/bugs161/pr102733/_x (java-22)
$ java -cp . Invoker
```

You see, `Invoker` prints nothing, because the generated byte code is as expected.

Now, try the same with an ECJ or batch compiler snapshot after branch `BETA_JAVA22` was merged onto the main branch (I tried with commit b2705b00e91be7b06d36d75bdd6e052450991021):

```text
$ java -jar org.eclipse.jdt.core.compiler.batch-3.38.0-SNAPSHOT.jar -8 -proceedOnError Invoker.java C.java
----------
1. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\Invoker.java (at line 4)
C.main(null);
^^^^
The method main(null) is undefined for the type C
----------
2. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\C.java (at line 1)
blahblahpackage pack;
^
The preview feature Unnamed Classes and Instance Main Methods is only available with source level 22 and above
----------
3. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\C.java (at line 1)
blahblahpackage pack;
^^^^^^^^^^^^^^^
blahblahpackage cannot be resolved to a type
----------
4. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\C.java (at line 1)
blahblahpackage pack;
^
Implicitly declared class must have a candidate main method
----------
5. ERROR in C:\Users\alexa\Documents\java-src\AspectJ\tests\bugs161\pr102733\_x\C.java (at line 4)
public static void main(String[] argv) {}
^^^^^^^^^^^^^^^^^^^
The method main cannot be declared static; static methods can only be declared in a static or top level type
----------
5 problems (5 errors)

$ java -cp . Invoker
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method main(null) is undefined for the type C

at Invoker.main(Invoker.java:4)
```

You see that despite compiling with a target less than 22, there is the ***"The preview feature Unnamed Classes and Instance Main Methods is only available with source level 22 and above"*** error. The byte code also looks rather like what would be expected in Java 22, because it creates a class `C` instead of what it thinks is an unnamed class and also an inner class `C.C` (albeit, not static).

In a nutshell: The byte code generated by 3.38-SNAPSHOT breaks compatibility, because both structure and behaviour are different than in 3.36.0.

I cannot compare the behaviour to Javac, because it does not have a feature similar to `-proceedOnError`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.