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

Scala hash code of some Double objects is different when it is seen as Double and when it is seen as Any #5640

Closed
scabug opened this issue Apr 2, 2012 · 9 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Apr 2, 2012

The same object d below has different scala hash code
when it is seen as static type Double and when it is seen as static type Any .

def testHashHash {
  val d = (BigInt(1) << 64).toDouble
  val a: Any = d
  println("d.hashCode="+d.hashCode)
  println("d.##="+d.##)
  println("a.##="+a.##)
  assert(d.## == a.##)
}

This is because BoxesRunTime.hashFromDouble(java.lang.Double n) and ScalaRunTime.hash(dv: Double) don't match.

@scabug
Copy link
Author

scabug commented Apr 2, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5640?orig=1
Reporter: @nadezhin
Affected Versions: 2.9.1, 2.10.0
Other Milestones: 2.10.0

@scabug
Copy link
Author

scabug commented May 8, 2012

@magarciaEPFL said:
Minimized further:

scala> val d = (BigInt(1) << 64).toDouble
d: Double = 1.8446744073709552E19

scala> val a: Any = d
a: Any = 1.8446744073709552E19

scala> scala.Double.box(d).hashCode()
res0: Int = 1139802112

scala> scala.runtime.ScalaRunTime.hash(d)
res1: Int = 1602224128

scala> scala.runtime.ScalaRunTime.hash(a)
res2: Int = 1139802112

@scabug
Copy link
Author

scabug commented May 8, 2012

@dgruntz said:
Actually, a and d have the same hashCode. It is ## which returns different results than hashCode for boxed numeric types (and for null) as documented.

scala> val d = (BigInt(1) << 64).toDouble
d: Double = 1.8446744073709552E19

scala> val a: Any = d
a: Any = 1.8446744073709552E19

scala> d.hashCode
res22: Int = 1139802112

scala> a.hashCode
res23: Int = 1139802112

So if this behavior is changed, do not forget to update the docs of ## as well.

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said (edited on May 8, 2012 10:50:50 PM UTC):

## isn't supposed to give different answers based on the static type of the argument.
That (x: Any).## != (x: Foo).## is definitely a bug.  This is already recognized in the doc for ##.
"if two value type instances compare as true, then ## will produce the same hash value for each of them."

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
Oh yeah, I forgot how irreconcilable this situation is. What I said is only true up to about 16 bits of width, then it becomes impossible.

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
58bb2d1bd2

@scabug scabug closed this as completed May 8, 2012
@scabug
Copy link
Author

scabug commented May 9, 2012

@dgruntz said:
runtime.BoxesRunTime.hashFromDouble(d) still returns the wrong value. Should that also be fixed, or is this method no longer used anywhere (in the context of ##)?
I claim that hashFromDouble should also check whether the argument can be represented correctly within a float and then return that hashCode.

scala> runtime.BoxesRunTime.hashFromNumber(d)
res16: Int = 1139802112

scala> runtime.BoxesRunTime.hashFromNumber(d.toFloat)
res17: Int = 1602224128

scala> d == d.toFloat
res18: Boolean = true

@scabug
Copy link
Author

scabug commented May 9, 2012

@paulp said:
Sorry, I'm doing things in a bit of a rush. I see there are redundant implementations in BoxesRunTime and ScalaRunTime, don't know why. If you are up for sending a pull request I'd be thrilled.

@scabug
Copy link
Author

scabug commented May 9, 2012

@dgruntz said:
really? here it is: b5919100e7

@scabug scabug added this to the 2.10.0-M3 milestone Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants