Ok, thanks for explaining this. I hadn't realized the conversions were designed to work without a source type.

I've removed the source type in the next revision: http://cr.openjdk.java.net/~jvernee/8241100/webrev.02/

Jorn

On 21/03/2020 06:08, John Rose wrote:
On Mar 20, 2020, at 10:49 AM, Jorn Vernee <jorn.ver...@oracle.com> wrote:
W.r.t. the source type being needed, I see the following 4 major cases:

1. src=Prim & dst=Prim -> cast convert. For boolean the least-significant-bit 
is used to convert it to/from an integer type.
2. src=Prim & dst=Ref   -> box the source value and potentially cast
3. src=Ref   & dst=Prim -> apply an unboxing conversion if possible and then a 
casting conversion (with same trick for boolean as (1))
4. src=Ref   & dst=Ref   -> reference cast

Without the source type we can't disambiguate between cases (2) and (4), or (1) 
and (3) because the bootstrap takes Object as an input.
I think that if you box the src=Prim from 1 or 2 and then
hand the resulting src=Ref to 3 or 4 you will get the same
thing.  The basic design here is that dst=Prim is the key
signal that unlocks the primitive conversions.  The type
of the src (Ref or Prim) doesn’t change the access to the
primitive conversions.

For (2) and (4) the bootstrap invocation mechanism takes care of the boxing for 
us, and the cast is performed by (4). For (1) and (3) the conversion code for 
the latter handles conversion of wrapper types to Number and then to the target 
primitive per (1). In the end things seems to work out to the same result 
(though maybe I'm missing some subtle difference in a failure case).
Indeed they do.  That’s how I designed it.  The upshot is that
Object is a reliable carrier even of primitive values, for these
APIs.

What I'm mostly worried about is that the source type already affects _how_ the 
conversion is done, and the fact that this difference is not observable seems 
somewhat incidental.... Coupled with the fact that asType and 
explicitCastArguments also have access to both the source and destination type, 
I think maybe the new bootstrap method should as well. After all, what if the 
set of cases is extended (valhalla?) and/or not being able to disambiguate 
starts to matter?
You shouldn’t be appealing to an internal function here for
designing the semantics.  The dual arguments to the internal
function are excess information; the shape of that function
predates the design decision described above.

Instead, appeal to some pseudocode, such as:

var id = identity(Object.class);
var mt = methodType(dst, Object.class);
var conv = explicitCastArguments(id, mt);
return conv.invoke(x);

I think that will give us all conversions we will need.

---

I've written a more in-depth specification for the bootstrap, and 
re-implemented it using explicitCastArguments, since that helps to catch 
discrepancies between the input value and the source type. Here is the next 
iteration: http://cr.openjdk.java.net/~jvernee/8241100/webrev.01

I've kept the source type for now, if it should be removed the specification 
can be trimmed down (since there would be less cases to specify).

As for the name; I think "asType" might be confusing since the applied conversion is not 
quite the same as MethodHandle::asType. Since the bootstrap is implemented in terms of 
explicitCastArguments I went with "explicitCast", how is that?
Yes, I like that name.

— John

Reply via email to