Skip to content

Conversation

@mbazley2
Copy link

What it does

InferenceContext18.solve() was assuming that it is always safe to cast from InvocationSite to ASTNode. These two classes are not actually related, but the only thing the resulting variable was being used for was to call sourceStart() and sourceEnd(), two methods that are defined on both classes.

A cleaner solution is to use the existing InvocationSite.EmptyWithAstNode wrapper class, which includes a passthrough implementation of the two relevant methods.

How to test

This should be functionally equivalent to the previous code, but the old cast was very inconvenient for my project that uses the ECJ as a base for implementing operator overloading in Java.

Author checklist

@iloveeclipse
Copy link
Member

@mbazley2 :

  1. You need to sign ECA. See https://api.eclipse.org/git/eca/status/gh/eclipse-jdt/eclipse.jdt.core/4522
  2. Could you please provide a reproducer for the problem & a regresion test?

@mbazley2
Copy link
Author

  1. I have signed the ECA, but it looks like Git is using an old email address for some reason. Is there any way to get it to recognise my current one? The "Common troubleshooting tips" section hints that there is, but doesn't actually say how.
  2. The reproducer for the problem is to create a fake InvocationSite for e.g. transparently converting the code "a + b" into "a.add(b)", which is something I assume you don't want in the main repository. I am not aware of any way to cause the ClassCastException I suffered using only vanilla Java code.

@iloveeclipse
Copy link
Member

  1. Is there any way to get it to recognise my current one

Yes, change the author email in your git commit, amend and force push it again.

@iloveeclipse
Copy link
Member

You can also set it permanently in .git/config file for your forked JDT repo:

[user]
	email = your@mail

@mbazley2 mbazley2 force-pushed the recordpatterninference branch from dbb6958 to 5fed78b Compare October 15, 2025 11:38
@stephan-herrmann
Copy link
Contributor

Thanks for the PR

InferenceContext18.solve() was assuming that it is always safe to cast from InvocationSite to ASTNode. These two classes are not actually related,

True, but since all these types are internal, we can easily see that "almost all" classes implementing InvocationSite actually extend (directly or indirectly) ASTNode. This leaves us with only 3 classes (EmptyWithAstNode + 2 anonymous classes), for which it should be possible to argue that their instances will never find their way into InferenceContext18.solve().

but the only thing the resulting variable was being used for was to call sourceStart() and sourceEnd(), two methods that are defined on both classes.

A cleaner solution is to use the existing InvocationSite.EmptyWithAstNode wrapper class, which includes a passthrough implementation of the two relevant methods.

Using such a wrapper in itself feels a bit like a workaround, too. Maybe it's time to invent an interface Location and wire it into the existing hierarchy, so that InferenceContext18.solve() can simple be written as solve(boolean,Location), leaving its callers unchanged. WDYT?

@stephan-herrmann
Copy link
Contributor

I just came across another candidate that might benefit from the proposed interface Location: ProblemReporter.isClassPathCorrect(char[][], CompilationUnitDeclaration, Object, boolean, ReferenceBinding) 😄

@mbazley2
Copy link
Author

Maybe it's time to invent an interface Location and wire it into the existing hierarchy, so that InferenceContext18.solve() can simple be written as solve(boolean,Location), leaving its callers unchanged. WDYT?

The same thought occurred to me, but I was trying to submit the minimum possible diff in the hopes that it would be more likely to get accepted. I could try implementing such a thing instead if you want.

@stephan-herrmann
Copy link
Contributor

Maybe it's time to invent an interface Location and wire it into the existing hierarchy, so that InferenceContext18.solve() can simple be written as solve(boolean,Location), leaving its callers unchanged. WDYT?

The same thought occurred to me, but I was trying to submit the minimum possible diff in the hopes that it would be more likely to get accepted. I could try implementing such a thing instead if you want.

Small is beautiful. Small without a wrapper is even more beautiful. 😄 I don't think introducing a slim interface Location will bloat the change (the biggest part might be the copyright header which you may copy-adjust from any existing file). So, if you want to give it a try this will be appreciated.

As a proof of its usefulness you might even want to use it also in ProblemReporter.isClassPathCorrect() (see above).

@mbazley2 mbazley2 force-pushed the recordpatterninference branch from eb6430a to 45a284b Compare October 22, 2025 16:32
@mbazley2
Copy link
Author

mbazley2 commented Oct 22, 2025

Looks like the pipeline fell victim to another occurrence of eclipse-platform/eclipse.platform.releng.aggregator#2660. Rebased again to see if that fixes it.

Copy link
Contributor

@stephan-herrmann stephan-herrmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

essentially looks good.

After we discussed that small is beautiful I believe you could still shrink the change a bit, see detailed comments.

Comment on lines +19 to +20
default int nameSourceStart() { return sourceStart(); }
default int nameSourceEnd() { return sourceEnd(); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see much benefit in declaring nameSourceStart()/End() here. Those don't seem to be useful for ASTNode and many of its subclasses. Nor do I see this called via the Location interface. Am I missing anything?

TypeConstants.JAVA_LANG_OBJECT,
this.referenceContext,
this.environment.missingClassFileLocation, false, null/*resolving j.l.O is not specific to any referencing type*/);
this.environment, false, null/*resolving j.l.O is not specific to any referencing type*/);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change looks unmotivated to me. Wouldn't just changing the signature of isClassPathCorrect() simplify things already?
I don't think that method has use for the LookupEnvironment itself.

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.

3 participants