Skip to content

Override equals and hashCode for WrappedArray#5551

Closed
alexeyr wants to merge 1 commit intoscala:2.12.xfrom
alexeyr:wrappedarray-hashcode-equals
Closed

Override equals and hashCode for WrappedArray#5551
alexeyr wants to merge 1 commit intoscala:2.12.xfrom
alexeyr:wrappedarray-hashcode-equals

Conversation

@alexeyr
Copy link
Copy Markdown
Contributor

@alexeyr alexeyr commented Nov 21, 2016

Avoid unnecessary boxing when calling equals or hashCode on WrappedArrays.

@scala-jenkins scala-jenkins added this to the 2.12.2 milestone Nov 21, 2016
@alexeyr
Copy link
Copy Markdown
Contributor Author

alexeyr commented Nov 21, 2016

The error is - library/mima failed: java.lang.RuntimeException: MiMa failed with exit code 2. Is it something I need to handle?

@szeiger
Copy link
Copy Markdown
Contributor

szeiger commented Nov 23, 2016

@alexeyr See the log of validate-test for details. The private[scala] methods are not binary compatible at the JVM level. Should be OK to whitelist though.

def update(index: Int, elem: Unit) { array(index) = elem }
override def hashCode = MurmurHash3.wrappedArrayHash(array)
override def equals(that: Any) = that match {
case that: ofUnit => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just compare by length?

  case that: ofUnit => array.length == that.array.length

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial thought, but we could somehow end up with an Array[Unit] containing null at runtime and I decided to err in favor of safety.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're hoping for any kind of correctness, null would have to be treated as being identical to () in this case. This is true for all primitive types. You can get null instead of the type's proper default value due to the way in which Scala abstracts over primitive types (and practically atavistic types such as void).

Just some of the weirdness:

scala> class A[T] { var x: T = _ } // a convenient way to get nulls of primitive types
defined class A

scala> new A[Unit]
res0: A[Unit] = A@359b650b

scala> res0.x // looks like we have ()

scala> println(res0.x) // null leaking when "converting" back to AnyRef
null

scala> res0.x == ((): Unit) // even scalac believes that this has to be true
<console>:13: warning: comparing values of types Unit and Unit using `==' will always yield true
       res0.x == ((): Unit)
              ^
res4: Boolean = false

scala> Array[Unit](res0.x)
res6: Array[Unit] = Array(())

scala> res6(0)

scala> println(res6(0)) // whoa, this one's actually correct
()

scala> new Array[Unit](1)
res9: Array[Unit] = Array(())

scala> println(res9(0)) // default is null again
null

scala> res9(0) = res0.x

scala> println(res9(0)) // still null
null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

@alexeyr
Copy link
Copy Markdown
Contributor Author

alexeyr commented Nov 24, 2016

There is also the question of whether overrides for ArrayOps should be added too. On one hand, ArrayOps objects should only be a result of implicit conversion and immediately disappear, on the other I don't think there are any drawbacks to providing the overrides.

@lrytz lrytz assigned szeiger and lrytz and unassigned lrytz Nov 25, 2016
@szeiger
Copy link
Copy Markdown
Contributor

szeiger commented Nov 25, 2016

I wouldn't bother with ArrayOps. It's supposed to be only implicitly created. Unless you perform the conversion explicitly or use an explicit type ascription (neither of which I would want to encourage), you cannot call equals or hashCode on it.

@szeiger
Copy link
Copy Markdown
Contributor

szeiger commented Dec 8, 2016

Ah, I should have merged this before merge conflicts start creeping in. The Conflict will probably resolve itself after #5590 though.

@adriaanm
Copy link
Copy Markdown
Contributor

Closing in favor of the rebased one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants