Skip to content

Conversation

mberndt123
Copy link

@mberndt123 mberndt123 commented Aug 24, 2025

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.

@mberndt123 mberndt123 force-pushed the sip-67-strict-equality-improvements branch from 3bf5df8 to e3d22ab Compare August 26, 2025 21:14
@mberndt123 mberndt123 force-pushed the sip-67-strict-equality-improvements branch from e3d22ab to 0a565d0 Compare August 26, 2025 21:14
@Gedochao Gedochao requested review from odersky and noti0na1 August 27, 2025 11:19
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
Copy link
Contributor

@odersky odersky Aug 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some remarks:

  1. 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.

  2. We cannot implement a SIP change without going through an experimenal language import.

  3. 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 two CanEqual.

Copy link
Author

@mberndt123 mberndt123 Aug 31, 2025

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.

@odersky odersky assigned mberndt123 and unassigned odersky Aug 30, 2025
@mberndt123 mberndt123 requested a review from a team as a code owner August 31, 2025 20:54
@mberndt123 mberndt123 force-pushed the sip-67-strict-equality-improvements branch 3 times, most recently from 2bb5197 to e9fb60b Compare August 31, 2025 21:17
@mberndt123 mberndt123 force-pushed the sip-67-strict-equality-improvements branch from e9fb60b to 4f7a9a3 Compare August 31, 2025 21:46
@mberndt123 mberndt123 requested a review from odersky August 31, 2025 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants