eclipse-jdt / eclipse-jdt/eclipse.jdt.core
Reconsider interning of capture bindings
- Dominant language
- Java
- Stars
- 237
- Forks
- 195
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 47
Description
From #2321:
Consider this example:
```
class Test {
public void test() {
B b1 = new B<>();
B b2 = new B<>();
A> a = this::error; // This makes both B parameters use the same capture variable
}
public void error(B a, B b) {}
interface A {
void run(T t1, T t2);
}
class B {}
}
```
ecj accepts the assignment while javac rejects, saying:
```
error: incompatible types: invalid method reference
A> a = this::error; // This makes both B parameters use the same capture variable
^
method error in class Test cannot be applied to given types
required: Test.B,Test.B
found: Test.B,Test.B
reason: inference variable T has incompatible equality constraints CAP#1,CAP#2
where T is a type-variable:
T extends Object declared in method error(Test.B,Test.B)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?
```
Debugging inference for this assignment I can see that descriptorParametersAsArgumentExpressions() answers twice the same type `B` in the position where javac seems to create two distinct captures.
ecj unifies both types because TypeSystem.getCapturedWildcard() is invoked twice with the exact same ingredients (same wildcard and same source positions), and so the capture is shared. Given that both parameter types originate from the same type variable `` this unification seems justified by common sense, but frankly this is not spelled out in JLS. [5.1.10. Capture Conversion](https://docs.oracle.com/javase/specs/jls/se22/html/jls-5.html#jls-5.1.10) unconditionally speaks of "a fresh type variable".
This "interning" was introduced in commit 2156fedd. When I disable it, I see the same two errors as reported by javac, but also regressions in:
* NegativeLambdaExpressionsTest.test432759()
* LambdaExpressionTest: test577466, testBug577719, testBug577719_2, testIssue2065
* GenericTypeTest:
* test0394, test0459, test0684, test0685, test0946, test1363, test426836, test434118
* this might actually improve: test0884 (see comment in the test)
* GenericsRegressionTest_1_8: testBug424710, testBug425798, testBug426836, testBug432110
To check:
* are those regressions actual failures, or perhaps some would align us better with javac?
* perhaps interning isn't bad per se but the fake arguments of a reference expression should still get distinct captures (although we don't have distinct source positions).
Contributor guide
Assessment
This issue has not been assessed yet.