summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-02-28 14:35:50 +0000
committerPaul Phillips <paulp@improving.org>2010-02-28 14:35:50 +0000
commitba5dbbd44db2c23c7532cde13453c6a031afb6e5 (patch)
tree00fbae4846f215cf90efda508f924cb790537e31 /src
parent432e16ce906cb1f03aabe26c0e51674780f44625 (diff)
downloadscala-ba5dbbd44db2c23c7532cde13453c6a031afb6e5.tar.gz
scala-ba5dbbd44db2c23c7532cde13453c6a031afb6e5.tar.bz2
scala-ba5dbbd44db2c23c7532cde13453c6a031afb6e5.zip
Added ## method to Any as our scala hashCode me...
Added ## method to Any as our scala hashCode method which provides consistent answers for primitive types. And I'm sure we're all tired of new starrs, but it's hard to add a method to Any without one. This patch only brings ## into existence, but nothing calls it yet. // some true assertions scala> assert(5.5f.## == 5.5f.hashCode) scala> assert(5.0f.## != 5.0f.hashCode && 5.0f.## == 5L.##) No review. (Already reviewed by odersky.)
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala15
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala17
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala5
7 files changed, 46 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
index d9830f7462..90261288ee 100644
--- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
@@ -94,6 +94,7 @@ abstract class ScalaPrimitives {
final val AS = 81 // x.as[y]
final val ISERASED = 85 // x.is$erased[y]
final val ASERASED = 86 // x.as$erased[y]
+ final val HASH = 87 // x.##
// AnyRef operations
final val SYNCHRONIZED = 90 // x.synchronized(y)
@@ -215,6 +216,7 @@ abstract class ScalaPrimitives {
addPrimitive(Any_!=, NE)
addPrimitive(Any_isInstanceOf, IS)
addPrimitive(Any_asInstanceOf, AS)
+ addPrimitive(Any_##, HASH)
// java.lang.Object
addPrimitive(Object_eq, ID)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 048d0b7bec..35a5f80d1f 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -423,6 +423,8 @@ abstract class GenICode extends SubComponent {
genArithmeticOp(tree, ctx, code)
else if (code == scalaPrimitives.CONCAT)
(genStringConcat(tree, ctx), STRING)
+ else if (code == scalaPrimitives.HASH)
+ (genScalaHash(receiver, ctx), INT)
else if (isArrayOp(code))
genArrayOp(tree, ctx, code, expectedType)
else if (isLogicalOp(code) || isComparisonOp(code)) {
@@ -1167,6 +1169,19 @@ abstract class GenICode extends SubComponent {
ctx1
}
+ /** Generate the scala ## method.
+ */
+ def genScalaHash(tree: Tree, ctx: Context): Context = {
+ val hashMethod = {
+ ctx.bb.emit(LOAD_MODULE(definitions.ScalaRunTimeModule))
+ definitions.getMember(definitions.ScalaRunTimeModule, "hash")
+ }
+
+ val ctx1 = genLoad(tree, ctx, ANY_REF_CLASS)
+ ctx1.bb.emit(CALL_METHOD(hashMethod, Static(false)))
+ ctx1
+ }
+
/**
* Returns a list of trees that each should be concatenated, from
* left to right. It turns a chained call like "a".+("b").+("c") into
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 11ec664904..0ea34235b2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -151,6 +151,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
def arrayUpdateMethod = getMember(ScalaRunTimeModule, "array_update")
def arrayLengthMethod = getMember(ScalaRunTimeModule, "array_length")
def arrayCloneMethod = getMember(ScalaRunTimeModule, "array_clone")
+ def scalaRuntimeHash = getMember(ScalaRunTimeModule, "hash")
// classes with special meanings
lazy val NotNullClass = getClass("scala.NotNull")
@@ -388,12 +389,14 @@ trait Definitions extends reflect.generic.StandardDefinitions {
var Any_toString : Symbol = _
var Any_isInstanceOf: Symbol = _
var Any_asInstanceOf: Symbol = _
+ var Any_## : Symbol = _
// members of class java.lang.{Object, String}
var Object_eq : Symbol = _
var Object_ne : Symbol = _
var Object_== : Symbol = _
var Object_!= : Symbol = _
+ var Object_## : Symbol = _
var Object_synchronized: Symbol = _
lazy val Object_isInstanceOf = newPolyMethod(
ObjectClass, "$isInstanceOf",
@@ -769,13 +772,15 @@ trait Definitions extends reflect.generic.StandardDefinitions {
Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype)
Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype)
Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype)
+ Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype) setFlag FINAL
Any_isInstanceOf = newPolyMethod(
AnyClass, nme.isInstanceOf_, tparam => booltype) setFlag FINAL
Any_asInstanceOf = newPolyMethod(
AnyClass, nme.asInstanceOf_, tparam => tparam.typeConstructor) setFlag FINAL
- // members of class java.lang.{Object, String}
+ // members of class java.lang.{ Object, String }
+ Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype) setFlag FINAL
Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype) setFlag FINAL
Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype) setFlag FINAL
Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype) setFlag FINAL
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 40e2551500..295dba2b46 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -214,6 +214,7 @@ trait StdNames extends reflect.generic.StdNames { self: SymbolTable =>
val PERCENT = encode("%")
val EQL = encode("=")
val USCOREEQL = encode("_=")
+ val HASHHASH = encode("##")
val Nothing = newTermName("Nothing")
val Null = newTermName("Null")
@@ -289,6 +290,7 @@ trait StdNames extends reflect.generic.StdNames { self: SymbolTable =>
val getCause = newTermName("getCause")
val getClass_ = newTermName("getClass")
val getMethod_ = newTermName("getMethod")
+ val hash_ = newTermName("hash")
val hashCode_ = newTermName("hashCode")
val hasNext = newTermName("hasNext")
val head = newTermName("head")
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 617967383a..79bc6bbba5 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -943,6 +943,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
tree,
SelectFromArray(qual, name, erasure(qual.tpe)).copyAttrs(fn),
args)
+
+ case Apply(fn @ Select(qual, _), Nil) if (fn.symbol == Any_## || fn.symbol == Object_##) =>
+ Apply(gen.mkAttributedRef(scalaRuntimeHash), List(qual))
+
case Apply(fn, args) =>
if (fn.symbol == Any_asInstanceOf)
fn match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 7012fa177a..252b1571a4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -26,6 +26,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
// inherits abstract value `global' and class `Phase' from Transform
import global._
+ import definitions.{ IntClass, UnitClass, ByNameParamClass, Any_asInstanceOf, Object_## }
/** the following two members override abstract members in Transform */
val phaseName: String = "superaccessors"
@@ -44,7 +45,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
private def transformArgs(args: List[Tree], params: List[Symbol]) =
((args, params).zipped map { (arg, param) =>
- if (param.tpe.typeSymbol == definitions.ByNameParamClass)
+ if (param.tpe.typeSymbol == ByNameParamClass)
withInvalidOwner { checkPackedConforms(transform(arg), param.tpe.typeArgs.head) }
else transform(arg)
}) :::
@@ -75,10 +76,16 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
- private def transformSuperSelect(tree: Tree) = tree match {
- case Select(sup @ Super(_, mix), name) =>
+ private def transformSuperSelect(tree: Tree): Tree = tree match {
+ // Intercept super.## and translate it to this.##
+ // which is fine since it's final.
+ case Select(sup @ Super(_, _), nme.HASHHASH) =>
+ Select(gen.mkAttributedThis(sup.symbol), Object_##) setType IntClass.tpe
+
+ case Select(sup @ Super(_, mix), name) =>
val sym = tree.symbol
val clazz = sup.symbol
+
if (sym.isDeferred) {
val member = sym.overridingSymbol(clazz);
if (mix != nme.EMPTY.toTypeName || member == NoSymbol ||
@@ -338,7 +345,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
if (isDependentType) {
val preciseTpe = expectedTpe.asSeenFrom(singleType(NoPrefix, obj), ownerClass) //typeRef(singleType(NoPrefix, obj), v.tpe.symbol, List())
- TypeApply(Select(res, definitions.Any_asInstanceOf),
+ TypeApply(Select(res, Any_asInstanceOf),
List(TypeTree(preciseTpe)))
} else res
}
@@ -364,7 +371,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (protAcc == NoSymbol) {
protAcc = clazz.newMethod(field.pos, nme.protSetterName(field.originalName))
protAcc.setInfo(MethodType(protAcc.newSyntheticValueParams(List(clazz.typeOfThis, field.tpe)),
- definitions.UnitClass.tpe))
+ UnitClass.tpe))
clazz.info.decls.enter(protAcc)
val code = DefDef(protAcc, {
val obj :: value :: Nil = protAcc.paramss.head;
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index ca8549bffa..a65ec05401 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -174,6 +174,11 @@ object ScalaRunTime {
case _ => false
}
+ /** Just a stub for now, but I think this is where the Predef.hash
+ * methods should be.
+ */
+ @inline def hash(x: Any): Int = Predef.hash(x)
+
/** Given any Scala value, convert it to a String.
*
* The primary motivation for this method is to provide a means for