From jens at lidestrom.se Sun Nov 27 12:29:04 2022 From: jens at lidestrom.se (=?UTF-8?Q?Jens_Lidestr=c3=b6m?=) Date: Sun, 27 Nov 2022 13:29:04 +0100 Subject: On range checks in primitive patterns Message-ID: Dear Amber expert group, I have followed the discussion on primitive patterns and wish to make a comment. The expert group is most certainty already aware of the issue, but I don't know if it has been discussed enough and I wish to draw attention to it. It seems to me that there are attractive aspects of the current proposal in [1], in which a pattern match operation on integral types perform a range check on its operand, so that `i instanceof byte b` matches if `i` is in the range of a byte. However, I think the following is a problematic aspect of this model: There is no syntactic difference between a pattern that perform only a variable binding, and a pattern that performs a range check. For example, the following pattern perform a range check if the record component is declared to be `long` but not otherwise: ``` switch (o) { ??? case SomeRecord(int i) -> System.out.println("Match"); ??? ... } ``` This has the following consequences: * When writing the pattern it's easy to make mistakes, forgetting to check the type of the record component, and out of habit declare the type in the pattern as `int`. If the record happens to contain a `long` this become a range check by mistake. This will often not be caught by the compiler and the pattern will simply not match in unexpected ways. * When updating the type of the record component, for example from `int` to `long`, it is easy to forget that this might change patterns. Patterns that previously only performed a variable binding now makes a range check. This will often not be caught by the compiler. Admittedly, this situation is similar to how type patterns and sub-classing work already. But I think the problem with integral primitive types is worse, because it is more implicit and easier for programmers to forget about. This problem is also somewhat similar to how total patterns accepts null while non-total patterns rejects null. I think these kinds of semantic differences between similar-looking constructs is something to be very wary about in programming languages! Possible solutions: * Only allow simple variable bindings in type patterns for integral types. Don't do range checking in patterns at all. (To me this seems like the best approach.) * Find an alternative syntax for patterns that perform range checks. (This is related to a suggestion from Tagir Valeev to this list on 2022-11-16 17:50.) Thank you, expert group, for your good work! It it truly a treat for a language enthusiast to be able to follow your discussions on these lists. Best regards, Jens Lidestr?m [1]: https://bugs.openjdk.org/browse/JDK-8288476 -------------- next part -------------- An HTML attachment was scrubbed... URL: