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
== returns true when comparing a boxed NaN with itself (the same boxed instance) #11698
Comments
OK, this is worse than I thought. And that's when you look more attentively to #6492. Because if any data structure scala> eqeq(List(Double.NaN), List(Double.NaN))
res2: Boolean = false
scala> eqeqItself(List(Double.NaN))
res3: Boolean = true And at that point, the only way to fix it is to completely remove the fast path for That is probably not acceptable, and this is what was discussed 10 years ago at https://www.scala-lang.org/old/node/4254. So I guess that's a won't fix? Ah! If only we got rid of cooperative equality for good! This issue, along many others, would be gone. |
I'm inclined to agree that it's a won't fix.
|
This comment was marked as outdated.
This comment was marked as outdated.
@eed3si9n I'm afraid you're missing the point. Here we see a violation of this principle: |
This comment has been minimized.
This comment has been minimized.
@noinline def equalsToSelf[A](a: A) = a == a
@noinline def specializedEqualsToSelf[@specialized A](a: A) = a == a
println(equalsToSelf(Double.NaN)) // true
println(specializedEqualsToSelf(Double.NaN)) // false |
I know the topic has been brought up several times in the past (#10112, scala/scala-dev#329, #6492, #2574), and typically discarded as as-designed, but I think found one case that is genuinely incorrect, as a result of an incorrect optimization:
In fact I think this distilled problem was part of the report in #6492, but it was mixed with other things and thus too easily dismissed.
The issue here is that, although a boxed NaN is supposed to compare with a boxed NaN as not
==
, there is one way to make it returntrue
: if we compare it with itself, as in, the exact same instance ofjava.lang.Double
.The cause of this issue is that
BoxesRunTime.equals
starts by short-circuiting the casex == y
astrue
(this is Java code, so==
is reference equality) athttps://github.com/scala/scala/blob/935ff010e1404062dadcfb39b23e99d637fe57c7/src/library/scala/runtime/BoxesRunTime.java#L118
That optimization is not correct when
x
andy
are both the same boxed NaN.I'm not sure how to fix this without affecting the performance of
==
. If performance considerations are not an issue, an easy fix would be to replace thetrue
by a call toisNotNaN(x)
defined asThe text was updated successfully, but these errors were encountered: