8000 ecj-javac record type inference difference by mpalat · Pull Request #3796 · eclipse-jdt/eclipse.jdt.core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

ecj-javac record type inference difference #3796

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.

8000

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

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mpalat
Copy link
Contributor
@mpalat mpalat commented Mar 14, 2025

WIP - DRAFT

			interface I<T> {}
			record R<T>(T t) {}

			public class X  {

			    static <T> boolean foo(R<T> y) {
			       if (y.t() instanceof R(var v)) {
			            var t = new R<>(v);
			            R<Object> r = t; //error  shown [Type mismatch: cannot convert from R<capture#2-of ?> to R<Object>]
			            return true;
			        }
			        return false;
			    }
			    public static void main(String argv[]) {
			        System.out.println(foo(new R<R<Object>>(new R<>(new X()))));
			    }
			}

What it does

Test case that shows difference between javac and ecj behaviour. javac compiles and prints true while running while ecj gives the following error:
"Type mismatch: cannot convert from R<capture#2-of ?> to R"

How to test

The code above is a reproducible testcase. Currently t 8000 he fix is in the works. The patch contains the test case only as of now.

Author checklist

@mpalat mpalat added this to the 4.36 milestone Mar 14, 2025
@mpalat mpalat marked this pull request as draft March 14, 2025 05:53
@mpalat mpalat requested a review from stephan-herrmann March 14, 2025 05:53
@mpalat mpalat self-assigned this Mar 14, 2025
@stephan-herrmann
Copy link
Contributor

In the test case I see three different things called "T".
Has it been written somewhere that all type parameters are called "T"?
Do yourself a favor and invest those 10 seconds to 'invent' different names.
How else do you want to keep track which is which?

@stephan-herrmann
Copy link
Contributor

Preliminary comments:

We perform record type inference with an expression of type <T>, an unbounded type variable.

From the items of 18.5.5 I see only these as applicable:

  • 2: so an initial bound set is created (which however is empty due to lack of declared bounds)
  • 5: resolution without sufficient information creates a CaptureBinding18 Z#0-T#0
  • 6: I see upwards projection converting R<Z#0-T#0> into R<?>.

Note in particular that items 3 and 4 are not really applicable. There's one oddity in item 3: it's all about the case of T being a parameterized type, from which betas are derived and how further constraints are created for them. Hidden in that list of inapplicable steps there are two bullets for the "outer else", i.e., when T is not a parameterized type. But even that bullet is moot for our case, as it only derives further constraints from a type variable's bound, but our type variable has no bounds.

Let's assume for a moment that R<?> is the correct result from 6. Since 9e5215a we immediately capture that type to the R<capture#2-of ?> we see in the error message. We might discuss with @srikanth-sankaran the exact capturing story. See, e.g., that a few lines down in RecordPattern.resolveType() we say this.resolvedType.capture(..) on the already captured type 😛

But none of this would transform the wildcard (captured or not) into type j.l.Object as required for accepting the program.

Next idea: perhaps somewhere down the line we treat <T> as having no bound, where perhaps we should regard it as <T extends Object>, but even adding explicit extends Object to all type parameters, doesn't help.

Ergo: for the moment I have no idea, what could lead us to inferring R<Object>.

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

Successfully merging this pull request may close these issues.

2 participants
0