Unchecked cast unchecked?
Archie Cobbs
archie.cobbs at gmail.com
Wed Oct 30 13:26:42 UTC 2024
Alex & Maurizio,
Thanks for the explanations & for creating the Jira issue.
FWIW here¹ is where I ran across this in real life.
-Archie
[1]
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java#L163-L166
On Wed, Oct 30, 2024 at 5:18 AM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:
> Good catch - I believe the compiler does what it does because it uses the
> type of the cast (as well as the types of the aruments) to determine the
> final compile-time type of the method being called. This is the type that
> will (under erasure) be reified in the constant pool. So, here javac sees a
> call to a method that returns V and then a cast to V...
>
> Ideally javac should erase things earlier, or just use Object as the type
> of the method call, as Alex suggests. The latter might be slightly
> complicated because, after we added VarHandle support in Java 9, we also
> have some polymorphic methods whose return type is not Object (see
> VarHandle::compareAndSet). But, basically, javac should implement this more
> closely, w/o getting too distracted by the type inferred for the synthetic
> symbol attached to the method call AST node:
>
> The compile-time result is determined as follows:
>
> -
>
> If the signature polymorphic method is either void or has a return
> type other than Object, the compile-time result is the result of the
> invocation type of the compile-time declaration (§15.12.2.6
> <https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.12.2.6>).
>
> -
>
> Otherwise, if the method invocation expression is an expression
> statement, the compile-time result is void.
> -
>
> Otherwise, if the method invocation expression is the operand of a
> cast expression (§15.16
> <https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.16>),
> the compile-time result is the erasure of the type of the cast expression (
> §4.6
> <https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.6>
> ).
>
>
> -
>
> Otherwise, the compile-time result is the signature polymorphic
> method's return type, Object.
>
> Filed:
> https://bugs.openjdk.org/browse/JDK-8343286
>
> Cheers
> Maurizio
>
>
> On 29/10/2024 22:52, Alex Buckley wrote:
>
> VarHandle::getAndSet(Object[]) is a signature polymorphic method, which
> means that the type of a method call is sensitive to an ensuing cast:
>
> "... 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)." (JLS 15.12.3)
>
> This has implications for how the method call is compiled, but it's moot
> for your program because the type of the method call is Object no matter
> how you slice it.
>
> Casting from Object to type variable V is achieved by a narrowing
> reference conversion that is unchecked. So, I'd expect an "unchecked cast"
> warning, like for a non-signature polymorphic method.
>
> Alex
>
> On 10/29/2024 2:30 PM, Archie Cobbs wrote:
>
> Question: Should this program generate an unchecked cast warning?
>
> import java.lang.invoke.VarHandle;
> class VarHandleCast<V> {
> VarHandle vh;
> V method(Object obj) {
> return (V)vh.getAndSet(this, obj); // unchecked cast?
> }
> }
>
> Currently, it does not.
>
> Presumably that has something to do with this code in Types.java but I'm
> not sure why this would mean there should be no warning:
>
> /**
> * A polymorphic signature method (JLS 15.12.3) is a method that
> * (i) is declared in the java.lang.invoke.MethodHandle/VarHandle
> classes;
> * (ii) takes a single variable arity parameter;
> * (iii) whose declared type is Object[];
> * (iv) has any return type, Object signifying a polymorphic return
> type; and
> * (v) is native.
> */
> public boolean isSignaturePolymorphic(MethodSymbol msym) {
> List<Type> argtypes = msym.type.getParameterTypes();
> return (msym.flags_field & NATIVE) != 0 &&
> (msym.owner == syms.methodHandleType.tsym || msym.owner ==
> syms.varHandleType.tsym) &&
> argtypes.length() == 1 &&
> argtypes.head.hasTag(TypeTag.ARRAY) &&
> ((ArrayType)argtypes.head).elemtype.tsym ==
> syms.objectType.tsym;
> }
>
> Thanks,
> -Archie
>
> --
> Archie L. Cobbs
>
>
>
--
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20241030/616323f1/attachment-0001.htm>
More information about the compiler-dev
mailing list