Hi Ragnar,
thank you for your response, this is very useful information.
Do I read this correctly that strictEqualityPatternMatchingsolved 11 out of 45 error messages (24%) in submodule R and 98 out of 124 (79%) in module A? That is 64% overall, which is not a bad result IMO.
Regarding comparisons of singletons/enum cases with ==: this was observed before in this thread, shoutout to @dontgitit. Since you’re already the second person to point this out, it does seem to be a real issue, and it should be fairly simple to implement. I support that change, but I think it can be dealt with in a separate SIP to avoid slowing down strictEqualityPatternMatching (which I hope to get approved for 3.9).
The problem is that just checking if two types have the same static type is not very safe
42 == "foo" // obviously shouldn't compile
val a: Any = 42
val b: Any = "foo"
a == b // would compile with the "same static type" rule; I don't think it should
And the compiler will eagerly “upcast” values if that helps making things compile. So it was decided that the clearest and safest approach is to just make things explicit: if you want to make comparisons, add derives CanEqual.
It has been argued that a CanEqual instance should be available by default for case classes and/or enums, but there are good reasons to be sceptical about that. For one thing, you can have things in your case classes that cannot be meaningfully compared, like functions. And having some kind of fully automatic typeclass derivation is a whole other can of worms, it’s unfortunately much messier than it seems.
Actually it works for both. The feature was originally designed to allow pattern matching on ADTs. Since Scala 2 doesn’t have ADTs but encodes them as sealed hierarchies of case classes and case objects, that’s what I designed the feature to support: case objects – add a case modifier and you’re good to go.
Arguably we could just drop that requirement because it doesn’t really matter if it has a case modifier. This would be in line with the fact that for instance Mirror.SumOf doesn’t care if the objects in your ADT have a case modifier or not. I think I’ll amend the SIP accordingly, thanks for pointing it out!
Yes, the standard library definitely needs more CanEqual instances! Fortunately, it was recently opened for improvements and I will definitely push for more CanEqual instances.
Given that null is not considered idiomatic Scala, I’m not convinced this needs to be addressed at the language level, also because we have alternatives:
- use an unboxed Option type that uses
nullunder the hood- in fact I think one should be added to the standard library
- use
eqto perform comparisons againstnull- we might want to add a compiler hint/quickfix to remind people it’s there
The only way to get there is one step at a time, and strictEqualityPatternMatching is one of the steps.