FWIW I agree with Dan’s point.
The Carrier API should throw IAE if Object does *not* appear in all the
MethodType places where the eventual (mysterious encapsulated) carrier
object will appear.
If tomorrow we figure out a clever use for client-specified types there
(such as Record or List), then mandating Object today will give us
flexibility to extend tomorrow.
Also, I don’t see any plausible use cases for a client-specified
carrier-placeholder type other than Object.
Also, mandating Object will make it slightly easier to deal with the
problem of static prediction (for static-image applications that Dan
referred to), since there’s one less degree of dynamic freedom.
On 9 Mar 2022, at 7:03, Dan Heidinga wrote:
On Wed, Mar 9, 2022 at 9:26 AM Brian Goetz <brian.go...@oracle.com>
wrote:
The minimal constraint is that the return type of the constructor
MH is the same type as the argument type of the component MHs.
Agreed. The types should match but they shouldn't be considered
part
of the api. I don't think (correct me if I'm wrong) that we want
them
to "escape" and be baked into classfiles. The implementation of the
anonymous class holding the fields ("holder object") should remain
as
a hidden implementation detail. One way to do that is to enforce
that
the holder object is always hidden behind other public types like
Object.
Yes. So my question is, who does the laundry? Is it the carrier API
(who always says Object), or the caller who is going to take the
return value of the carrier constructor and stick it in an Object?
Does it make a difference? If I take the constructor MH, and compose
it with the component MHs, will having an extraneous Object signature
make it harder to expose the true type (which may be a Q type), or
will that routinely and reliably come out in the wash anyway?
Having the Carrier api do the laundry ensures that the implementation
details don't leak into MH/MT constantpool entries. And encourages
users not to try to be overly clever and rely on the implementation
details. The more they do that the harder it will be to evolve the
implementation in the future.
The Q-ness should just flow through the APIs - I don't see an extra
cost here. Either it's all used in the same JIT compilation unit and
there's full type visibility or its not and the Q may have to hit the
heap to flow along the callstack. The costs are the same whether the
descriptors say Q or not.
It would seem to me that preserving stronger types here dynamically
gives MH combinators more room to optimize?
Only the outer edge of the MH chain would need to return
(constructor)
/ take (component) Object. The implementation of the MHs can use a
sharper type. I don't think we gain any optimization abilities here
by exposing the sharper type - at worst there's an asType operation
to
check the type but that shouldn't be visible in the performance
profile.
OK, so you’re saying it’s fine to slap an Object label on it, as
it will come off easily when needed.
That's my assertion.