summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala8
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala30
-rw-r--r--test/files/run/bug4752.scala10
3 files changed, 37 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index c855abd7fb..0917646f76 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -126,6 +126,13 @@ trait SyntheticMethods extends ast.TreeDSL {
val method = syntheticMethod(nme.toString_, FINAL, makeNoArgConstructor(StringClass.tpe))
typer typed { DEF(method) === LIT(clazz.name.decode) }
}
+ def moduleHashCodeMethod: Tree = {
+ val method = syntheticMethod(nme.hashCode_, FINAL, makeNoArgConstructor(IntClass.tpe))
+ // The string being used as hashcode basis is also productPrefix.
+ val code = clazz.name.decode.hashCode
+
+ typer typed { DEF(method) === LIT(code) }
+ }
def forwardingMethod(name: Name, targetName: Name): Tree = {
val target = getMember(ScalaRunTimeModule, targetName)
@@ -262,6 +269,7 @@ trait SyntheticMethods extends ast.TreeDSL {
)
// methods for case objects only
def objectMethods = List(
+ Object_hashCode -> (() => moduleHashCodeMethod),
Object_toString -> (() => moduleToStringMethod)
)
// methods for both classes and objects
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 5a20b72fcd..4d5f783d61 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -177,18 +177,26 @@ object ScalaRunTime {
def _hashCode(x: Product): Int = {
import scala.util.MurmurHash._
val arr = x.productArity
- var h = startHash(arr)
- var c = startMagicA
- var k = startMagicB
- var i = 0
- while (i < arr) {
- val elem = x.productElement(i)
- h = extendHash(h, elem.##, c, k)
- c = nextMagicA(c)
- k = nextMagicB(k)
- i += 1
+ // Case objects have the hashCode inlined directly into the
+ // synthetic hashCode method, but this method should still give
+ // a correct result if passed a case object.
+ if (arr == 0) {
+ x.productPrefix.hashCode
+ }
+ else {
+ var h = startHash(arr)
+ var c = startMagicA
+ var k = startMagicB
+ var i = 0
+ while (i < arr) {
+ val elem = x.productElement(i)
+ h = extendHash(h, elem.##, c, k)
+ c = nextMagicA(c)
+ k = nextMagicB(k)
+ i += 1
+ }
+ finalizeHash(h)
}
- finalizeHash(h)
}
/** Fast path equality method for inlining; used when -optimise is set.
diff --git a/test/files/run/bug4752.scala b/test/files/run/bug4752.scala
new file mode 100644
index 0000000000..3d5c166a7a
--- /dev/null
+++ b/test/files/run/bug4752.scala
@@ -0,0 +1,10 @@
+object Test {
+ object Bippy {
+ case object Dingus
+ }
+
+ def main(args: Array[String]): Unit = {
+ assert(None.## == "None".##, None)
+ assert(Test.Bippy.Dingus.## == "Dingus".##, Test.Bippy.Dingus)
+ }
+}