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

Synthetic CanEqual for primitives does not handle Nothing as a subtype #13739

Closed
jcracknell opened this issue Oct 12, 2021 · 6 comments · Fixed by #13828
Closed

Synthetic CanEqual for primitives does not handle Nothing as a subtype #13739

jcracknell opened this issue Oct 12, 2021 · 6 comments · Fixed by #13828
Assignees
Labels
area:implicits related to implicits itype:bug Spree Suitable for a future Spree
Milestone

Comments

@jcracknell
Copy link

As CanEqual is contravariant, this should be valid and is likely the root cause for issues around matching Nil/None under strict equality:

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

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

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

@odersky
Copy link
Contributor

odersky commented Oct 13, 2021

I agree this should be fixed. CanEqual[Int, Nothing] instances should be synthesizable.

@anatoliykmetyuk anatoliykmetyuk added the Spree Suitable for a future Spree label Oct 15, 2021
@SethTisue
Copy link
Member

SethTisue commented Oct 26, 2021

nitpick: in Scala 3, summon is more idiomatic than implicitly

is likely the root cause for issues around matching Nil/None under strict equality

what are those issues — what are you doing with Nil and None that isn't working? we'd like to test that, too, rather than only testing what summon calls work and don't

so far all I've found that fails is:

scala> ??? == 3
-- Error: ----------------------------------------------------------------------
1 |??? == 3
  |^^^^^^^^
  |Values of types Nothing and Int cannot be compared with == or !=
1 error found

while the same thing with String compiles.

@SethTisue
Copy link
Member

summon[CanEqual[3, Nothing]] fails just like summon[CanEqual[Int, Nothing]], so that's a test case to also include

it might not be any extra work to cover, since if one side is Nothing, as far as I can see it doesn't even matter what the other side is

@jcracknell
Copy link
Author

jcracknell commented Oct 26, 2021

@SethTisue 3e963c0 introduces CanEqual.canEqualOption[A] forcing a LUB computation as a workaround for this particular issue, which will occur for any type which would require derivation of CanEqual for a primitive and Nothing.

Under 3.0.2 prior to the addition of the workaround this did not work:
https://scastie.scala-lang.org/C3pjrS3vTAWC4tqC9bkSgw

@SethTisue
Copy link
Member

SethTisue commented Oct 26, 2021

ah, I see #13512 now, I had not noticed that link before

since if one side is Nothing, as far as I can see it doesn't even matter what the other side is

and I see there was already some discussion on this at #12419

general reference on CanEqual: https://docs.scala-lang.org/scala3/reference/contextual/multiversal-equality.html

@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
Labels
area:implicits related to implicits itype:bug Spree Suitable for a future Spree
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants