eclipse-jdt / eclipse-jdt/eclipse.jdt.core
ECJ Fails to report Incompatible Type Comparison involving class literals of interface types vs javac
- Dominant language
- Java
- Stars
- 237
- Forks
- 195
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 47
Description
### Environment:
ECJ Version:
```
Eclipse Compiler for Java(TM) v20241112-0530, 3.40.0, Copyright IBM Corp 2000, 2020. All rights reserved.
```
Java Version:
```java
openjdk version "21.0.6" 2025-01-21 LTS
OpenJDK Runtime Environment Temurin-21.0.6+7 (build 21.0.6+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.6+7 (build 21.0.6+7-LTS, mixed mode)
```
Javac Version:
```
javac 21.0.6
```
### Description:
Hi~, we have discovered an issue in ECJ when analyzing lambda expressions under OpenJDK 21. Specifically, ECJ fails to detect incompatible type comparisons inside lambda expressions, allowing erroneous code to compile successfully.
Consider the following test program:
```jsx
public class Correct {
public static void main(String[] strArr) {
Correct c1 = new Correct();
if (c1.getClass() == Object.class) { //ERROR HERE
System.out.println("true");
}
}
}
```
Both `javac` and `ecj` correctly report the following compilation error for this program:
```
1. ERROR in /Correct.java (at line 6)
if (c1.getClass() == Object.class) { //ERROR HERE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Incompatible operand types Class and Class
----------
1 problem (1 error)
```
However, when we move the type comparison inside a lambda expression, ECJ fails to detect the issue:
```java
public class BugRevealing {
public static void main(String[] strArr) {
java.io.ObjectInputFilter.Config.setSerialFilterFactory((context, currentFilter) -> {
if (context.getClass() == Object.class) {
return java.io.ObjectInputFilter.Config.createFilter("com.example.*;!*");
}
return currentFilter;
});
}
}
```
When compiled using `javac`, the compiler correctly reports the following error:
```
BugRevealing.java:6: error: incomparable types: Class and Class
if (context.getClass() == Object.class) {
^
where CAP#1 is a fresh type-variable:
CAP#1 extends ObjectInputFilter from capture of ? extends ObjectInputFilter
1 error
```
However, when compiling with ECJ, **no errors are reported**, and a `.class` file is successfully generated.
To further demonstrate this issue, we provide a test case where the erroneous code path is actually executed at runtime:
```java
import java.io.*;
public class SerializationExample implements Serializable {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
java.io.ObjectInputFilter.Config.setSerialFilterFactory((context, currentFilter) -> {
context = new ObjectInputFilter() {
@Override
public Status checkInput(FilterInfo filterInfo) {
return null;
}
};
if (context.getClass() == Object.class) { //ERROR HERE
System.out.println("true");
return java.io.ObjectInputFilter.Config.createFilter("com.example.*;!*");
}
System.out.println("false");
return currentFilter;
});
try {
SerializationExample obj = new SerializationExample();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
In this program, we modify the test case to ensure the erroneous type comparison is actually executed. As expected, when compiled using `javac`, it correctly fails with a compilation error. However, **ECJ compiles it successfully, and the program executes without issues**.
Running the generated `.class` file produces the following output:
```java
>java -cp . SerializationExample
false
```
This clearly demonstrates that ECJ fails to detect the type mismatch inside lambda expressions.
ECJ should report the same compilation error as `javac`, or at least the same error as it does outside of lambda expressions, when an incompatible type comparison occurs within a lambda. The fact that ECJ successfully compiles this erroneous code suggests a potential flaw in its type inference mechanism.
This bug could lead to silent type-related issues in Java applications, as developers may unknowingly introduce type mismatches without any compiler warnings.
Would appreciate your insights into this issue. Thanks!
### Steps to Reproduce:
1. **Compile the test program using ECJ:**
```
java -jar ecj-4.34.jar -21 -d . BugRevealing.java
```
- **Expected behavior:** ECJ should report a compilation error due to the incompatible type comparison.
- **Actual behavior:** Compilation succeeds, generating a `.class` file without any error.
2. **Compile the test program using Javac:**
```java
javac -cp . BugRevealing.java
```
Contributor guide
Assessment
This issue has not been assessed yet.