Bridging the divide between unconditionalitty and exhaustiveness for ReferenceType patterns
Brian Goetz
brian.goetz at oracle.com
Thu Oct 12 13:22:16 UTC 2023
Backing up, what you're saying here is that both total and partial
reference type patterns have opinions about nullity (null-accepting and
null-rejecting, respectively), and while these may be reasonable
defaults, you would like to be able to "override" these defaults. I
sympathize.
There was much discussion about whether we needed a separate way of
saying something like (T|Null), or T-but-not-null, explicitly. As you
can imagine, many syntaxes were proposed, but they were all unsatisfying
because (a) they ceded much syntactic real estate (and therefore much
mindshare) to a distinction that was small, and often ignorable, and (b)
if we ever got nullity control in the future (T! and T?), these ad-hoc
pattern forms would look permanently silly.
On 10/11/2023 7:25 PM, Steffen Yount wrote:
> Amber devs,
>
> For the Patterns available to us in Java 21 it has been noted that:
> 1) TypePatterns match unconditionally, that is to say they are "null
> matching". Meanwhile RecordPatterns at most match exhaustively leaving
> null valued ReferenceTypes in the remainder, that is to say
> RecordPatterns are "non-null matching" or "instance matching".
>
> 2) It's the "null hostility" of the "switch" and "instanceof"
> operators that prevents TypePatterns from matching/dominating the null
> values there:
>
> * In the case of "switch" a null valued ReferenceType selector
> expression will cause a NullPointerException to be thrown by the
> switch operator unless the "case null" switch label has been declared
> in its switch block.
>
> * In the case of "instanceof" evaluation, when the the
> RelationalExpression is null valued, null is interpreted semantically
> as "not an instance" and thus also as "not an instance of" the
> ReferenceType (or Pattern) found to the right of the "instanceof" keyword.
>
>
> This dichotomy between TypePatterns and RecordPatterns illustrates a
> gap in current pattern matching coverage wherein we cannot match null
> vs non-null vs nullable for non-record ReferenceTypes.
>
> I would love to see this gap closed.
>
> In JEP 455, I can see there's a lot of work going into making Patterns
> work well with PrimitiveTypes, is anyone looking into making Patterns
> work better with these ReferenceTypes?
>
> What are your thoughts on closing this pattern matching coverage gap
> and maybe implementing something like the following:
>
> The current Java 21 Pattern definitions look like
>
> Pattern:
> TypePattern
> RecordPattern
>
> The TypePattern part could be deconstructed and extended giving new
> Pattern definitions that look more like:
>
> Pattern:
> PrimitivePattern (PrimitiveType)
> RecordPattern (non-null valued record ReferenceType)
> InstancePattern (non-null valued ReferenceType)
> NullPattern (null valued ReferenceType)
> ReferencePattern (ReferenceType)
>
> Notes:
> 1) The InstancePattern matching a ReferenceType T and the NullPattern
> matching that same ReferenceType T are complements of each other and
> exhaustively cover the match space of a ReferencePattern matching that
> same ReferenceType T
>
> 2) The ReferencePattern matching a ReferenceType T dominates both a
> NullPattern and a InstancePattern matching that same ReferenceType T
>
> 3) The RecordPattern matching a record ReferenceType T for a Record
> declared with a zero-arg constructor exhaustively covers the
> InstancePattern matching that same ReferenceType T
>
> 4) The InstancePattern matching a record ReferenceType T dominates a
> RecordPattern matching that same ReferenceType T
>
> Sample of proposed Pattern notation:
>
> match-only Pattern notation:
> PrimitivePattern: int
> RecordPattern: Bat(_,_)
> InstancePattern: Bat()
> NullPattern: null
> ReferencePattern: Bat
>
> match+projection Pattern notation:
> PrimitivePattern: int ii
> RecordPattern: Bat(_,_) bb
> InstancePattern: Bat() bb
> NullPattern: null bb
> ReferencePattern: Bat bb
>
> (When matched, the pattern's named variables are projected into the
> appropriate declaration scope)
>
> Proposed Pattern appearance and idiomatic familiarity:
> PrimitivePattern: Resembles a local PrimitiveType variable declaration
> RecordPattern: Resembles an "all-args" constructor call for a
> record ReferenceType
> InstancePattern: Resembles a "no-args" constructor call for a
> ReferenceType
> NullPattern: Resembles a ReferencePattern where the
> ReferenceType has been replaced with the NullLiteral
> ReferencePattern: Resembles a local ReferenceType variable declaration
>
> Does this notation feel good and Java-ish to you? Have you already got
> something better figured out? Your thoughts?
>
> Thanks for your consideration,
> -Steffen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20231012/6c0141a5/attachment.htm>
More information about the amber-dev
mailing list