diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala | 8 | ||||
-rw-r--r-- | src/library/scala/runtime/ScalaRunTime.scala | 30 | ||||
-rw-r--r-- | test/files/run/bug4752.scala | 10 |
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) + } +} |