A peek at the roadmap for pattern matching and more
Brian Goetz
brian.goetz at oracle.com
Fri Aug 14 17:42:42 UTC 2020
> Aside: My understanding of the MethodParameters attribute is that it's
> intended more as an informational than API and unlikely to affect
> application behaviour at runtime.
The existing MP attribute represents a somewhat unfortunate compromise.
The EE folks (remember EE?) had a compelling-enough use case for being
able to reflect over parameter names, which was that they wanted to
generate various remote-invocation stubs (corba, *RPC, etc) from
classes, but felt that having to annotate each parameter
(`foo(@MyNameIs("bob") String bob)`) would suck. So they wanted us to
reify the parameter names by default in the classfile, for reflection to
serve up.
The ME folks (remember ME?) freaked out; "Whoa, more bytes in the
classfile, you have to make that optional, and not the default!"
The EE guys came back with "OK, how about driving retention based on an
annotation."
We said (for the zillion'th time): You know that's not what annotations
are for.
So the compromise was to make it a tooling option; invoke `javac` with
`-parameters`. Result: no one can count on them.
Now, the MP attribute itself should not need to change here; only the
conditions under which the language promises to make these available for
reflection and condition the compatibility rules.
> Making names significant and part of the API will affect refactoring
> and separate compilation: developers are used to being able to freely
> rename parameters without worrying about affects on other parts of
> their code base or about breaking their consumers (library authors).
> Are there things the language can do to help with name transitions?
> Is treating parameter name changes in a __byname method as a breaking
> API change something that developers will have to adapt to?
Note that we already have this problem with records; the name of a
component in records flows into constructor descriptors, accessor names,
etc. It is an open question whether the developers can handle the
responsibility :)
I have long wanted to have widely available, easy to use tooling that
could detect incompatible changes between versions of a module, where it
would look at the old bytecode and say "whoa, you did <incompatible
thing> there, did you mean to?" In the presence of such tooling, this
would be one more set of assertions for such a mechanism. But so far I
haven't gotten my wish. (Perhaps our IDE friends are cooking something
like this up?) I do think that detection of incompatible changes is
something for tooling to handle, not the language. But I agree that
this is a concern, and more so than for records, which have the
component names stapled to their forehead.
> Similarly libraries that implement a common specification (Java EE,
> etc) have historically allowed each implementation to name the
> parameters in ways that made sense for their implementation. I can
> see this becoming "names are API, live with it" which is a reasonable
> answer but one that will take some time to filter thru the ecosystem
> after the feature is released. Any concerns that adopting this
> feature forces a "flag day" on consumers of such libraries with all
> implementors needing to move in lockstep?
I think the real challenge here is ensuring that, if the decision is
made to make a member __byname, that they understand the consequences.
("Nah, that could never change!", said every developer ever,
incorrectly.) Overuse of __byname could easily become a problem. (I
think also you're observing that this is in a sense worse than "names
are API, live with it"; really, it's "names are *sometimes* API, live
with that!"?)
A member going from insignificant to significant naming should be a
compatible move, as should (eventually) adding a named parameter with a
default to a constructor (though there's more work to do here to make
this compatible.) The rule about telescoping chains is there in part to
allow us to evolve such members and leave the old entry points around.
The flag day is when we realize "crap, that name really is so terrible
we have to change it."
> In the "Refining overloading" section [2]
> > Each __byname constructor / deconstructor can be invoked
> positionally, so it must follow
> > the existing rules for overloading and overload selection. A set of
> __byname members is
> > valid if and only if for each two such members, their name sets are
> either disjoint or one
> > is a proper subset of the other and the types corresponding to the
> common names are the same.
> This seems like an answer to the refactoring concerns above as it
> provides a way to leave previous API points around to not break
> consumers. Will the normal deprecation schemes apply to these
> name-only overloads? If so it covers most of the refactoring concerns
> - though the need to leave the old API points is a bit of code smell
> that may discourage some kinds of refactoring. Time will tell.
Yes. The real concern is (when we get to default parameters) that, if
you have seventeen parameters already, that you'll have 18 tomorrow is
virtually a guarantee. This is tricky ground, I think I have a story
though.
> Is the intention that the VM would check the disjoint constraints
> during classloading? I can see it being pushed to the VM to validate
> or left as a language level rule with the VM's resolution taking the
> first available match. At first glance, both seem reasonable though
> VM validation will incur startup costs and would need more clarity on
> how checks for duplicate __byname constructors would mesh with the
> "Factories" proposal, either disjoint or combined checks? Details to
> be worked out as the proposal progresses.
Asking the VM to check these seems a bit much, especially given that the
names exist primarily for overload selection, which is a language
concern. My thinking for by-name invocation is that we do overload
selection statically, pick a positional signature, and invoke with an
indy that treats that positional signature as a fast path, but falls
back to an ugly reflective linkage on fail. This is the standard trick
of "replicate the language semantics at runtime in indy" so the VM
doesn't have to.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20200814/faab71e8/attachment.htm>
More information about the amber-spec-experts
mailing list