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

"Cannot cast from" error with generics with ECJ when javac compiles OK

Open
#1,188 0 comments 0 reactions 0 assignees View on GitHub
javac
Dominant language
Java
Stars
237
Forks
195
Avg merge
1d 10h
Merged PRs (30d)
49

Description

I observed a compilation error from some generated code that I was only encountering with ECJ and not javac. I saw some other existing issues regarding generic inference discrepancies with javac, but I saw that they seemed to be regarding wildcards while this doesn't have them. Apologies if it is the same issue.

```java
public class Example {

public static class GeneratedMessageLite<
MessageType extends GeneratedMessageLite,
BuilderType extends GeneratedMessageLite.Builder> {

private static class Builder<
MessageType extends GeneratedMessageLite,
BuilderType extends Builder> {}
}

public static final class Part extends GeneratedMessageLite {
public static Builder newBuilder() {
Part part = new Part();
return (Builder) part.createBuilder();
}

public static final class Builder extends GeneratedMessageLite.Builder {}

protected final <
MessageType extends GeneratedMessageLite,
BuilderType extends GeneratedMessageLite.Builder>
BuilderType createBuilder() {
return null;
}
}
}
```

ECJ:
```
$ java -jar .\ecj-3.34.0.jar -version
Eclipse Compiler for Java(TM) v20230523-1233, 3.34.0, Copyright IBM Corp 2000, 2020. All rights reserved.

$ java -jar .\ecj-3.34.0.jar .\Example.java -1.8
----------
1. ERROR in C:\Users\jacob\OneDrive\Desktop\proto\Example.java (at line 17)
return (Builder) part.createBuilder();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Cannot cast from Example.GeneratedMessageLite.Builder>,Example.GeneratedMessageLite.Builder,BuilderType>>,Example.GeneratedMessageLite.Builder,BuilderType>,BuilderType>> to Example.Part.Builder
----------
1 problem (1 error)
```

javac:
```
$ javac -version
javac 17.0.6
$ javac .\Example.java
[no error]
```

Notably, explicitly stating the generic types resolves the issue:
```diff
- return (Builder) part.createBuilder();
+ return (Builder) part.createBuilder();
```

Contributor guide

Open the contributing guide

Research direction

Start with the self-contained Example.java reproducer and run the ECJ 3.34.0 command shown in the report, then compare it with javac 17.0.6. Focus on the inferred generic types at the cast in Part.newBuilder and compare them with the explicit call; done means the valid implicit form no longer reports “Cannot cast from” while javac behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.