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