Skip to content
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

Equatability of Nothing with types which are otherwise unequatable #13512

Closed
jcracknell opened this issue Sep 12, 2021 · 4 comments · Fixed by #13828
Closed

Equatability of Nothing with types which are otherwise unequatable #13512

jcracknell opened this issue Sep 12, 2021 · 4 comments · Fixed by #13828
Assignees
Milestone

Comments

@jcracknell
Copy link

jcracknell commented Sep 12, 2021

I have been experimenting with strict equality in 3.0.2 and immediately ran into the issue where you cannot pattern match against Nil/None. I see the efforts to address this in 3.1.0 in 3e963c0 and 32a99fd, however I am not sure that this is the correct approach, as the following is still illegal:

class NotEquatable

List(new NotEquatable) match
  case Nil => ???

This can be addressed by instead adding the following givens permitting equating Nothing with any type regardless of the equatability of that type, on the basis that you could never actually invoke the equality test:

given canEqualNothingL: CanEqual[Nothing, Any] = CanEqual.derived
given canEqualNothingR: CanEqual[Any, Nothing] = CanEqual.derived

With this addition it appears you can remove the supplementary CanEqual.canEqual{Seq,Option} previously added to address matching Nil/None in the above-mentioned commits.

I will note that you do get this awkward behavior already present in 2.x:

??? == 42 // runtime error
42 == ??? // compile error, ambiguous overload

this could perhaps be addressed by adding an overload to Any, however I am uncertain of the viability of such an approach:

def equals(nothing: Nothing): Boolean = ???
@odersky
Copy link
Contributor

odersky commented Sep 22, 2021

Strict equality is not really set up to work with the current standard library. You can use it to experiment with your own types. The idea is that with enough experience gained we can do a better job on the next redesign of the standard library.

We need a lot more experiments with what the right givens for the various bits of equality would be. But I won't have the time to do it myself. But if others want to add new givens, run the community build and report back, that would be welcome!

@odersky odersky removed their assignment Sep 22, 2021
@jcracknell
Copy link
Author

jcracknell commented Oct 3, 2021

@odersky after posting this I had the nagging thought that it should be possible to derive CanEqual for equatable types with Nothing, as CanEqual is contravariant. Indeed under 3.0.2:

scala> implicitly[CanEqual[String, Nothing]]
val res0: CanEqual[String, Nothing] = scala.CanEqual$derived$@7c6b997b

scala> given [A, B](using CanEqual[A, B]): CanEqual[Option[A], Option[B]] = CanEqual.derived
def given_CanEqual_Option_Option
  [A, B](using x$1: CanEqual[A, B]): CanEqual[Option[A], Option[B]]

scala> Option.empty[String] match { case None => "works" }
val res1: String = works

scala> implicitly[CanEqual[Int, Nothing]]                                                                          
-- Error:
1 |implicitly[CanEqual[Int, Nothing]]
  |                                  ^
  |          Values of types Int and Nothing cannot be compared with == or !=

So there is a real bug here in that synthetic CanEqual for primitives fails to consider Nothing as a possible subtype:

https://github.com/lampepfl/dotty/blob/cf600613d96e676136363fd0de8e31a2ff998408/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala#L102-L114

@jcracknell
Copy link
Author

I've opened an issue for synthetic CanEqual in #13739 so it doesn't get missed, however the question of whether or not Nothing should be equatable with any other type regardless of its equatability remains.

@jcracknell jcracknell changed the title CanEqual for Nothing Equatability of Nothing with types which are otherwise unequatable Oct 13, 2021
deniszo added a commit to deniszo/dotty that referenced this issue Oct 26, 2021
@SethTisue
Copy link
Member

PR: #13828

olsdavis pushed a commit to olsdavis/dotty that referenced this issue Apr 4, 2022
@Kordyjan Kordyjan added this to the 3.1.2 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants