summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala32
3 files changed, 27 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index cec92d82c7..6f51638045 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -190,6 +190,8 @@ trait Definitions {
def Product_productArity = getMember(ProductRootClass, nme.productArity)
def Product_productElement = getMember(ProductRootClass, nme.productElement)
def Product_productPrefix = getMember(ProductRootClass, nme.productPrefix)
+ def Product_canEqual = getMember(ProductRootClass, nme.canEqual_)
+
val MaxProductArity = 22
/* <unapply> */
val ProductClass: Array[Symbol] = new Array(MaxProductArity + 1)
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index cc150d5809..65445b60d4 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -266,6 +266,7 @@ trait StdNames {
val box = newTermName("box")
val boxArray = newTermName("boxArray")
val forceBoxedArray = newTermName("forceBoxedArray")
+ val canEqual_ = newTermName("canEqual")
val checkInitialized = newTermName("checkInitialized")
val classOf = newTermName("classOf")
val copy = newTermName("copy")
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index b48aed76ab..2fdd049bc5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -118,7 +118,7 @@ trait SyntheticMethods extends ast.TreeDSL {
typer typed {
DEF(method) === {
- Apply(gen.mkAttributedRef(target), This(clazz) :: (method ARGNAMES))
+ Apply(REF(target), This(clazz) :: (method ARGNAMES))
}
}
}
@@ -141,6 +141,15 @@ trait SyntheticMethods extends ast.TreeDSL {
}
}
+ /** The canEqual method for case classes.
+ */
+ def canEqualMethod: Tree = {
+ val method = syntheticMethod(nme.canEqual_, 0, makeTypeConstructor(List(AnyClass.tpe), BooleanClass.tpe))
+ val that = method ARG 0
+
+ typer typed (DEF(method) === (that IS_OBJ clazz.tpe))
+ }
+
/** The equality method for case classes. The argument is an Any,
* but because of boxing it will always be an Object, so a check
* is neither necessary nor useful before the cast.
@@ -148,8 +157,8 @@ trait SyntheticMethods extends ast.TreeDSL {
* def equals(that: Any) =
* (this eq that.asInstanceOf[AnyRef]) ||
* (that match {
- * case this.C(this.arg_1, ..., this.arg_n) => true
- * case _ => false
+ * case x @ this.C(this.arg_1, ..., this.arg_n) => x canEqual this
+ * case _ => false
* })
*/
def equalsClassMethod: Tree = {
@@ -170,13 +179,21 @@ trait SyntheticMethods extends ast.TreeDSL {
// Creates list of parameters and a guard for each
val (guards, params) = List.map2(clazz.caseFieldAccessors, constrParamTypes)(makeTrees) unzip
+ // Verify with canEqual method before returning true.
+ def canEqualCheck() = {
+ val that: Tree = typer typed ((method ARG 0) AS clazz.tpe)
+ val canEqualOther: Symbol = clazz.info nonPrivateMember nme.canEqual_
+
+ (that DOT canEqualOther)(This(clazz))
+ }
+
// Pattern is classname applied to parameters, and guards are all logical and-ed
val (guard, pat) = (AND(guards: _*), clazz.name.toTermName APPLY params)
localTyper typed {
DEF(method) === {
(This(clazz) ANY_EQ that) OR (that MATCH(
- (CASE(pat) IF guard) ==> TRUE ,
+ (CASE(pat) IF guard) ==> canEqualCheck() ,
DEFAULT ==> FALSE
))
}
@@ -191,9 +208,7 @@ trait SyntheticMethods extends ast.TreeDSL {
def readResolveMethod: Tree = {
// !!! the synthetic method "readResolve" should be private, but then it is renamed !!!
val method = newSyntheticMethod(nme.readResolve, PROTECTED, makeNoArgConstructor(ObjectClass.tpe))
- typer typed {
- DEF(method) === gen.mkAttributedRef(clazz.sourceModule)
- }
+ typer typed (DEF(method) === REF(clazz.sourceModule))
}
def newAccessorMethod(tree: Tree): Tree = tree match {
@@ -240,7 +255,8 @@ trait SyntheticMethods extends ast.TreeDSL {
List(
Product_productPrefix -> (() => productPrefixMethod),
Product_productArity -> (() => productArityMethod(accessors.length)),
- Product_productElement -> (() => productElementMethod(accessors))
+ Product_productElement -> (() => productElementMethod(accessors)),
+ Product_canEqual -> (() => canEqualMethod)
)
}