<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>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...</p>
<p>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:</p>
<p>
<blockquote type="cite">The compile-time result is determined as
follows:
<div class="norm">
<ul class="norm" style="list-style-type: square; ">
<li class="listitem">
<p class="norm-static">If the signature polymorphic method
is either <code class="literal">void</code> or has a
return type other than <code class="literal">Object</code>,
the compile-time result is the result of the invocation
type of the compile-time declaration (<a class="xref" href="https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.12.2.6" title="15.12.2.6. Method Invocation Type">§15.12.2.6</a>).
</p>
</li>
<li class="listitem">
<p class="norm-static">Otherwise, if the method invocation
expression is an expression statement, the compile-time
result is <code class="literal">void</code>. </p>
</li>
<li class="listitem">
<p class="norm-static">Otherwise, if the method invocation
expression is the operand of a cast expression (<a class="xref" href="https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.16" title="15.16. Cast Expressions">§15.16</a>), the
compile-time result is the erasure of the type of the
cast expression (<a class="xref" href="https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.6" title="4.6. Type Erasure">§4.6</a>).</p>
</li>
</ul>
</div>
</blockquote>
<blockquote type="cite">
<div class="norm">
<ul class="norm" style="list-style-type: square; ">
<li class="listitem">
<p class="norm-static">Otherwise, the compile-time result
is the signature polymorphic method's return type, <code class="literal">Object</code>. </p>
</li>
</ul>
</div>
</blockquote>
</p>
<p>Filed:<br>
<a class="moz-txt-link-freetext" href="https://bugs.openjdk.org/browse/JDK-8343286">https://bugs.openjdk.org/browse/JDK-8343286</a><br>
</p>
<p>Cheers<br>
Maurizio<br>
</p>
<p><br>
</p>
<div class="moz-cite-prefix">On 29/10/2024 22:52, Alex Buckley
wrote:<br>
</div>
<blockquote type="cite" cite="mid:7ad3fb18-0335-4e05-b584-4c15ca979252@oracle.com">VarHandle::getAndSet(Object[])
is a signature polymorphic method, which means that the type of a
method call is sensitive to an ensuing cast:
<br>
<br>
"... 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)
<br>
<br>
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.
<br>
<br>
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.
<br>
<br>
Alex
<br>
<br>
On 10/29/2024 2:30 PM, Archie Cobbs wrote:
<br>
<blockquote type="cite">Question: Should this program generate an
unchecked cast warning?
<br>
<br>
import java.lang.invoke.VarHandle;
<br>
class VarHandleCast<V> {
<br>
VarHandle vh;
<br>
V method(Object obj) {
<br>
return (V)vh.getAndSet(this, obj); // unchecked cast?
<br>
}
<br>
}
<br>
<br>
Currently, it does not.
<br>
<br>
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:
<br>
<br>
/**
<br>
* A polymorphic signature method (JLS 15.12.3) is a method
that
<br>
* (i) is declared in the
java.lang.invoke.MethodHandle/VarHandle classes;
<br>
* (ii) takes a single variable arity parameter;
<br>
* (iii) whose declared type is Object[];
<br>
* (iv) has any return type, Object signifying a
polymorphic return type; and
<br>
* (v) is native.
<br>
*/
<br>
public boolean isSignaturePolymorphic(MethodSymbol msym) {
<br>
List<Type> argtypes =
msym.type.getParameterTypes();
<br>
return (msym.flags_field & NATIVE) != 0 &&
<br>
(msym.owner == syms.methodHandleType.tsym ||
msym.owner == syms.varHandleType.tsym) &&
<br>
argtypes.length() == 1 &&
<br>
argtypes.head.hasTag(TypeTag.ARRAY) &&
<br>
((ArrayType)argtypes.head).elemtype.tsym ==
syms.objectType.tsym;
<br>
}
<br>
<br>
Thanks,
<br>
-Archie
<br>
<br>
-- <br>
Archie L. Cobbs
<br>
</blockquote>
<br>
</blockquote>
</body>
</html>