Relaxed assignment conversions for sealed types
Dan Heidinga
heidinga at redhat.com
Tue Nov 24 15:23:58 UTC 2020
On Tue, Nov 24, 2020 at 10:02 AM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:
>
> On 24/11/2020 14:45, Remi Forax wrote:
>
>
>
> ------------------------------
>
> *De: *"Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> <maurizio.cimadamore at oracle.com>
> *À: *"Brian Goetz" <brian.goetz at oracle.com> <brian.goetz at oracle.com>,
> "Tagir Valeev" <amaembo at gmail.com> <amaembo at gmail.com>
> *Cc: *"amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> <amber-spec-experts at openjdk.java.net>
> *Envoyé: *Mardi 24 Novembre 2020 15:10:35
> *Objet: *Re: Relaxed assignment conversions for sealed types
>
>
> On 31/10/2020 23:30, Brian Goetz wrote:
>
>
>
> On Oct 25, 2020, at 10:06 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
>
> To make it clear that I'm not talking about the annoyance of typing the
> cast, let's pretend I'm suggesting to write it like this:
>
> BarImpl bi = (__static BarImpl) b;
>
>
> Pulling on this string some more — I think there’s a connection between
> this feature and total statement switches. We’ve been looking for a way to
> make statement switches total, and here, what we’re looking for is a way to
> make _casts_ total. Which suggests this is one feature, not two. So
> perhaps:
>
> switch-total (x) { … } // a switch, but with added bonus totality
> checking
>
> BarImpl b = (total BarImpl) bar // a cast, but with added bonus
> totality checking
>
> I agree the latter is a common enough problem when writing implementation
> code where you have a sealed hierarchy and you know there's only one impl
> (Foreign API has this all over the place).
>
>
> You think that not typechecking that BarImpl is the sole implementation of
> Bar everytime you write a cast is a problem ?
> I don't know for the Foreign API, but having a static helper method that
> takes a BarImpl and returns a Bar is not enough ?
>
> I'm saying that it's (in my humble experience) a common enough pattern
> that I've seen often enough, so what Brian is proposing doesn't seem
> completely crazy to me - e.g. having some more 1st class support in the
> language for this sort of stuff can be a good thing.
>
>
> BarImpl impl(Bar bar) {
> return switch(bar) { case BarImpl impl -> impl; };
> }
>
> Or am i missing something ?
>
> See first-class :-) Sure, there are other ways to get there.
>
>
> To throw in the mix - how is some kind of pattern match assignment (we
> referred to as a "let expression" in some of the earlier docs [1]) would
> change the picture here? In other words, maybe it's overloading `=` which
> is at odds here, and we need to make it more explicit that this is more
> akin to an extraction/match?
>
>
> The match operator (as in let ... match), is more or less what C# as done
> by using switch as an operator,
> BarImpl impl(Bar bar) {
> return bar switch { case BarImpl impl -> impl; };
> }
>
> It's still a possible syntax for total-switch.
> Anyway, it doesn't answer to your question, it seems you want something in
> the middle in between a cast and a switch, let impl = bar;
>
> I think all your references to switch expression reinforce my feeling that
> having a pattern-matching based way to declare local variables (as the
> document I linked in [1] shows with its __let construct) might be one way
> to skin this cat.
>
> Maurizio
>
>
> Looking at Remi's examples makes me agree more strongly that we need first
class support - can't you just hear the resounding "java's too verbose"
complaints about having to write the switch helper method and remember to
pepper your code with calls to "impl(bar)" rather than using casts as you
would elsewhere in your code?
I agree Brian's really onto something with suggesting the totality question
is the same for the two features. I'm in favour of going even further and
removing the cast to allow = to do double duty here for sealed types rather
than introducing new syntax for it. The new syntax ("__ construct" or
"(total BarImpl)") highlights "this is different" and I'm not sure we need
to do that for sealed types. Letting ='s do the work feels like a better
form of auto-boxing where javac does the compile-time analysis and errors
out for non-total cases or inserts the required total cast for the user.
This gives both compile time checking and runtime safety without needing to
beat the reader over the head about it.
We want to make it easier to read & write correct code - pushing the
analysis of totality for sealed types into javac does both for us.
--Dan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20201124/01add758/attachment-0001.htm>
More information about the amber-spec-experts
mailing list