Skip to content

Missing unchecked cast warning in polymorphic method call - #5260

Merged
stephan-herrmann merged 1 commit into
eclipse-jdt:masterfrom
stephan-herrmann:pr5256-fup
Jul 31, 2026
Merged

Missing unchecked cast warning in polymorphic method call#5260
stephan-herrmann merged 1 commit into
eclipse-jdt:masterfrom
stephan-herrmann:pr5256-fup

Conversation

@stephan-herrmann

Copy link
Copy Markdown
Contributor
  • Suppress CheckCast after polymorphic method call

Fixes #5256

See #5256 (comment) f.

+ Suppress CheckCast after polymorphic method call

Fixes eclipse-jdt#5256
@iloveeclipse

Copy link
Copy Markdown
Member

Do I see it right, the extra cast was not expected? If so, we should touch the platform bundle again like in eclipse-platform/eclipse.platform#2842 for the next build with this PR merged.

@stephan-herrmann

stephan-herrmann commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Do I see it right, the extra cast was not expected?

correct

If so, we should touch the platform bundle again like in eclipse-platform/eclipse.platform#2842 for the next build with this PR merged.

Has an I-build already picked up that touching? Otherwise we might be good already?

@stephan-herrmann
stephan-herrmann merged commit 5568ae3 into eclipse-jdt:master Jul 31, 2026
13 checks passed
@stephan-herrmann
stephan-herrmann deleted the pr5256-fup branch July 31, 2026 13:05
@iloveeclipse

Copy link
Copy Markdown
Member

Has an I-build already picked up that touching? Otherwise we might be good already?

Yes, I've built one already.
I will tuch that bundle again.

@iloveeclipse

Copy link
Copy Markdown
Member

Do I see it right, the extra cast was not expected?

correct

It seem counterintuitive? Could you help to understand this?

@stephan-herrmann

Copy link
Copy Markdown
Contributor Author

Do I see it right, the extra cast was not expected?

correct

It seem counterintuitive? Could you help to understand this?

I'll try, though those polymorphic method calls are not my everyday business either.

The declaration of methods like VarHandle.getAndSet() and MethodHandle.invokeExact() has signature (Object[])Object, i.e., they accept any arguments in any number, and produce some result.

JLS 15.2.3, however, defines the "compile-time parameter types" and "compile-time result" to be determined from the context, in particular:

...

  • Otherwise, if the method invocation expression is the operand of a cast expression (§15.16), the compile-time result is the erasure of the type of the cast expression (§4.6).

So, if you write ...

(String) methodHandle.invokeExact(a)

... the expression methodHandle.invokeExact(a) is considered to have a signature with String as its return type. IOW, the enclosing cast is not a conversion but informs the compiler about the assumed shape of the underlying method. Whether or not the actual MethodHandle satisfies the assumption is subject to runtime checking inside invokeExact. If you try to fool type checking instead of a ClassCastException you'll be greeted like this:

Exception in thread "main" java.lang.invoke.WrongMethodTypeException: handle's method type (CheckCast)CheckCast but found (CheckCast)String
	at java.base/java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:522)
	at java.base/java.lang.invoke.Invokers.checkExactType(Invokers.java:531)

Ergo, the invocation already "has" the type requested by the cast, so no additional check via a checkcast operation is needed.

Still the compiler should check for unsafe operations due to erasure. In the original example of #3651 a cast to a type variable V is something that the runtime cannot check, since V has no representation in byte code. Hence the compiler needs to perform that part of analysis that issues "unsafe cast" warnings (#5256), without, however, actually generating a checkcast (this PR).

Does this make sense?

I checked with javac, which also does not issue a checkcast for the two new tests.

@stephan-herrmann

Copy link
Copy Markdown
Contributor Author

To further expand on this part:

IOW, the enclosing cast is not a conversion but informs the compiler about the assumed shape of the underlying method.

The type information from the cast is then used for the signature in the invokevirtual bytecode, like:

2: invokevirtual #20  // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/Object;)Ljava/lang/String;

The String return type is derived from the cast, and replaces the original return type Object.

@iloveeclipse

Copy link
Copy Markdown
Member

OK, thanks.

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