-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implement SIP-67: strictEquality pattern matching (fixes #22732) #23803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement SIP-67: strictEquality pattern matching (fixes #22732) #23803
Conversation
3bf5df8
to
e3d22ab
Compare
e3d22ab
to
0a565d0
Compare
untpd.Select(untpd.TypedSplice(tree), nme.EQ), | ||
untpd.TypedSplice(dummyTreeOfType(pt))) | ||
typedExpr(cmp, defn.BooleanType) | ||
if ! (tree.tpe <:< pt && (tree.symbol.flags.isAllOf(Flags.EnumValue) || (tree.symbol.flags.isAllOf(Flags.Module | Flags.Case)))) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some remarks:
-
The motivation for the SIP was that it makes strictEquality easier to use, but this also changes the pattern matching behavior of patterns without that import. And it breaks the law that pattern matching values is done with an
==
check. I think this goes too far, even though this is what's specified in the SIP. -
We cannot implement a SIP change without going through an experimenal language import.
-
I think it would be better to add code to
assumedCanEqual
instead. Under strictEquality and the experimental import, if the left operand (or either one) is an enum constant, and the other operand is a supertype, assume the twoCanEqual
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @odersky,
Thank you for your review.
Regarding 1: 🤔 I'm not sure I understand. The SIP says “The semantics of pattern matching against a constant are otherwise unchanged”, meaning that it will still be equivalent to ==
, except it doesn't require CanEqual
. If that's not what it does, then it's a bug in my implementation. But I think that's solved by moving it to assumeCanEqual
as you suggested in point 3, right?
Regarding 2: ✅ I've added an experimental language import, strictEqualityPatternMatching
, to enable this behaviour. I also tried adding a Mode
for this so it can be enabled with a command line flag similar to -language:strictEquality
, but unless I'm misreading the code, the modes are stored in an Int
bitmask and all the bits are already taken 😒
Regarding 3: ✅ I've moved the implementation to assumedCanEqual
, which was a bit tricky because in that function the Tree
isn't available, but I need it to know if it's a case object
or enum case
. It's also called from Synthesizer
where there is no Tree
, so I'm passing it as an Option[Tree]
now.
2bb5197
to
e9fb60b
Compare
e9fb60b
to
4f7a9a3
Compare
Hi,
this is my attempt at implementing the SIP-67 specification. Thanks to @noti0na1 and @dwijnand for the hints you gave in #22732. Sorry it took so long, please let me know what you think.