Skip to content

Commit 59fc37a

Browse files
committed
Merge pull request scala#3497 from adriaanm/rebase-3464
Make Object#== override Any#==
2 parents c611f7b + 127a767 commit 59fc37a

18 files changed

+114
-59
lines changed

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ trait Infer extends Checkable {
174174
private lazy val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)
175175

176176
/** The context-dependent inferencer part */
177-
class Inferencer(context: Context) extends InferencerContextErrors with InferCheckable {
177+
abstract class Inferencer extends InferencerContextErrors with InferCheckable {
178+
def context: Context
178179
import InferErrorGen._
179180

180181
/* -- Error Messages --------------------------------------------------- */

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
109109

110110
private val transformed: mutable.Map[Tree, Tree] = unit.transformed
111111

112-
val infer = new Inferencer(context0) {
112+
val infer = new Inferencer {
113+
def context = Typer.this.context
113114
// See SI-3281 re undoLog
114115
override def isCoercible(tp: Type, pt: Type) = undoLog undo viewExists(tp, pt)
115116
}

src/library-aux/scala/AnyRef.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ trait AnyRef extends Any {
7676
* @param arg0 the object to compare against this object for equality.
7777
* @return `true` if the receiver object is equivalent to the argument; `false` otherwise.
7878
*/
79-
final def ==(that: AnyRef): Boolean =
80-
if (this eq null) that eq null
79+
final def ==(that: Any): Boolean =
80+
if (this eq null) that.asInstanceOf[AnyRef] eq null
8181
else this equals that
8282

8383
/** Create a copy of the receiver object.

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ trait Definitions extends api.StandardDefinitions {
3535
private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long): MethodSymbol = {
3636
val msym = owner.newMethod(name.encode, NoPosition, flags)
3737
val params = msym.newSyntheticValueParams(formals)
38-
msym setInfo MethodType(params, restpe) markAllCompleted
38+
val info = if (owner.isJavaDefined) JavaMethodType(params, restpe) else MethodType(params, restpe)
39+
msym setInfo info markAllCompleted
3940
}
4041
private def enterNewMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): MethodSymbol =
4142
owner.info.decls enter newMethod(owner, name, formals, restpe, flags)
@@ -904,8 +905,14 @@ trait Definitions extends api.StandardDefinitions {
904905
existentialAbstraction(clazz.unsafeTypeParams, clazz.tpe_*)
905906

906907
// members of class scala.Any
908+
909+
// TODO these aren't final! They are now overriden in AnyRef/Object. Prior to the fix
910+
// for SI-8129, they were actually *overloaded* by the members in AnyRef/Object.
911+
// We should unfinalize these, override in AnyValClass, and make the overrides final.
912+
// Refchecks never actually looks at these, so its just for consistency.
907913
lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL)
908914
lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL)
915+
909916
lazy val Any_equals = enterNewMethod(AnyClass, nme.equals_, AnyTpe :: Nil, BooleanTpe)
910917
lazy val Any_hashCode = enterNewMethod(AnyClass, nme.hashCode_, Nil, IntTpe)
911918
lazy val Any_toString = enterNewMethod(AnyClass, nme.toString_, Nil, StringTpe)
@@ -1012,8 +1019,8 @@ trait Definitions extends api.StandardDefinitions {
10121019

10131020
// members of class java.lang.{ Object, String }
10141021
lazy val Object_## = enterNewMethod(ObjectClass, nme.HASHHASH, Nil, IntTpe, FINAL)
1015-
lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, AnyRefTpe :: Nil, BooleanTpe, FINAL)
1016-
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, AnyRefTpe :: Nil, BooleanTpe, FINAL)
1022+
lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL)
1023+
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL)
10171024
lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, AnyRefTpe :: Nil, BooleanTpe, FINAL)
10181025
lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, AnyRefTpe :: Nil, BooleanTpe, FINAL)
10191026
lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_ => BooleanTpe)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
t8219-any-any-ref-equals.scala:5: error: method ==: (x$1: Any)Boolean does not take type parameters.
2+
"".==[Int]
3+
^
4+
t8219-any-any-ref-equals.scala:6: error: method ==: (x$1: Any)Boolean does not take type parameters.
5+
("": AnyRef).==[Int]
6+
^
7+
t8219-any-any-ref-equals.scala:7: error: method ==: (x$1: Any)Boolean does not take type parameters.
8+
("": Object).==[Int]
9+
^
10+
three errors found
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
// The error message tells us that AnyRef#== and Any#== are overloaded.
3+
// A real class couldn't define such an overload, why do we allow AnyRef
4+
// to do so?
5+
"".==[Int]
6+
("": AnyRef).==[Int]
7+
("": Object).==[Int]
8+
}

test/files/pos/t8219.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait Equalizer[T]
2+
trait Gen[A]
3+
4+
class Broken {
5+
implicit def const[T](x: T): Gen[T] = ???
6+
implicit def convertToEqualizer[T](left: T): Equalizer[T] = ???
7+
8+
def in(a: Any) = ()
9+
in {
10+
import scala.None // any import will do..
11+
"" == "" // this no longer triggers the bug, as Object#== now overrides Any#==
12+
}
13+
14+
// We can still trigger the bug with a structural type, see pending/neg/t8219.scala
15+
}

test/files/pos/t8219b.scala

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
trait Equalizer[T]
2+
trait Gen[A]
3+
4+
class Broken {
5+
implicit def const[T](x: T): Gen[T] = ???
6+
implicit def convertToEqualizer[T](left: T): Equalizer[T] = ???
7+
8+
def in(a: Any) = ()
9+
in {
10+
import scala.None // any import will do..
11+
"" == "" // no longer a problem, see pos/t8129.scala
12+
}
13+
14+
// We used to fall into the errant code path above when `Any#==` and `AnyRef#==`
15+
// were overloaded.
16+
//
17+
// Real classes couldn't get away with that overloading; it would result in
18+
// a compiler error because the variants would collapse into an overriding
19+
// relationship after erasure.
20+
//
21+
//
22+
// But, a structural type can! This triggers the same error, and served as
23+
// a backstop for this test if we change the signatures of `AnyRef#==` to
24+
// override `Any#==`.
25+
type T = {
26+
def a(a: AnyRef): Boolean
27+
def a(a: Any): Boolean
28+
}
29+
30+
def t: T = ???
31+
32+
in {
33+
import scala.None // any import will do..
34+
t.a("")
35+
}
36+
37+
// Or, we can get here with ambiguous implicits from the formal parameter
38+
// type of the less specific overload to that of the more specific.
39+
object T {
40+
def foo(a: Any) = true
41+
def foo(a: String) = true
42+
}
43+
in {
44+
import scala.None
45+
implicit def any2str1(a: Any) = ""
46+
implicit def any2str2(a: Any) = ""
47+
T.foo("")
48+
}
49+
}

test/files/presentation/callcc-interpreter.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: CallccInterpreter.scala
33
askTypeCompletion at CallccInterpreter.scala(51,34)
44
================================================================================
55
[response] askTypeCompletion at (51,34)
6-
retrieved 59 members
6+
retrieved 57 members
77
abstract trait Term extends AnyRef
88
abstract trait Value extends AnyRef
99
case class Add extends callccInterpreter.Term with Product with Serializable
@@ -38,10 +38,8 @@ def toString(): String
3838
def unitM[A](a: A): callccInterpreter.M[A]
3939
def →[B](y: B): (callccInterpreter.type, B)
4040
final def !=(x$1: Any): Boolean
41-
final def !=(x$1: AnyRef): Boolean
4241
final def ##(): Int
4342
final def ==(x$1: Any): Boolean
44-
final def ==(x$1: AnyRef): Boolean
4543
final def asInstanceOf[T0]: T0
4644
final def eq(x$1: AnyRef): Boolean
4745
final def isInstanceOf[T0]: Boolean

test/files/presentation/completion-implicit-chained.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@ reload: Completions.scala
33
askTypeCompletion at Completions.scala(11,16)
44
================================================================================
55
[response] askTypeCompletion at (11,16)
6-
retrieved 24 members
6+
retrieved 22 members
77
[inaccessible] protected[package lang] def clone(): Object
88
[inaccessible] protected[package lang] def finalize(): Unit
99
def equals(x$1: Any): Boolean
1010
def hashCode(): Int
1111
def map(x: Int => Int)(implicit a: DummyImplicit): test.O.type
1212
def toString(): String
1313
final def !=(x$1: Any): Boolean
14-
final def !=(x$1: AnyRef): Boolean
1514
final def ##(): Int
1615
final def ==(x$1: Any): Boolean
17-
final def ==(x$1: AnyRef): Boolean
1816
final def asInstanceOf[T0]: T0
1917
final def eq(x$1: AnyRef): Boolean
2018
final def isInstanceOf[T0]: Boolean

test/files/presentation/ide-bug-1000349.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: CompletionOnEmptyArgMethod.scala
33
askTypeCompletion at CompletionOnEmptyArgMethod.scala(2,17)
44
================================================================================
55
[response] askTypeCompletion at (2,17)
6-
retrieved 32 members
6+
retrieved 30 members
77
def +(other: String): String
88
def ->[B](y: B): (Foo, B)
99
def ensuring(cond: Boolean): Foo
@@ -17,10 +17,8 @@ def hashCode(): Int
1717
def toString(): String
1818
def →[B](y: B): (Foo, B)
1919
final def !=(x$1: Any): Boolean
20-
final def !=(x$1: AnyRef): Boolean
2120
final def ##(): Int
2221
final def ==(x$1: Any): Boolean
23-
final def ==(x$1: AnyRef): Boolean
2422
final def asInstanceOf[T0]: T0
2523
final def eq(x$1: AnyRef): Boolean
2624
final def isInstanceOf[T0]: Boolean

test/files/presentation/ide-bug-1000475.check

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: Foo.scala
33
askTypeCompletion at Foo.scala(3,7)
44
================================================================================
55
[response] askTypeCompletion at (3,7)
6-
retrieved 31 members
6+
retrieved 29 members
77
[inaccessible] protected[package lang] def clone(): Object
88
[inaccessible] protected[package lang] def finalize(): Unit
99
def +(other: String): String
@@ -18,10 +18,8 @@ def hashCode(): Int
1818
def toString(): String
1919
def →[B](y: B): (Object, B)
2020
final def !=(x$1: Any): Boolean
21-
final def !=(x$1: AnyRef): Boolean
2221
final def ##(): Int
2322
final def ==(x$1: Any): Boolean
24-
final def ==(x$1: AnyRef): Boolean
2523
final def asInstanceOf[T0]: T0
2624
final def eq(x$1: AnyRef): Boolean
2725
final def isInstanceOf[T0]: Boolean
@@ -37,7 +35,7 @@ final def wait(x$1: Long,x$2: Int): Unit
3735
askTypeCompletion at Foo.scala(6,10)
3836
================================================================================
3937
[response] askTypeCompletion at (6,10)
40-
retrieved 31 members
38+
retrieved 29 members
4139
[inaccessible] protected[package lang] def clone(): Object
4240
[inaccessible] protected[package lang] def finalize(): Unit
4341
def +(other: String): String
@@ -52,10 +50,8 @@ def hashCode(): Int
5250
def toString(): String
5351
def →[B](y: B): (Object, B)
5452
final def !=(x$1: Any): Boolean
55-
final def !=(x$1: AnyRef): Boolean
5653
final def ##(): Int
5754
final def ==(x$1: Any): Boolean
58-
final def ==(x$1: AnyRef): Boolean
5955
final def asInstanceOf[T0]: T0
6056
final def eq(x$1: AnyRef): Boolean
6157
final def isInstanceOf[T0]: Boolean
@@ -71,7 +67,7 @@ final def wait(x$1: Long,x$2: Int): Unit
7167
askTypeCompletion at Foo.scala(7,7)
7268
================================================================================
7369
[response] askTypeCompletion at (7,7)
74-
retrieved 31 members
70+
retrieved 29 members
7571
[inaccessible] protected[package lang] def clone(): Object
7672
[inaccessible] protected[package lang] def finalize(): Unit
7773
def +(other: String): String
@@ -86,10 +82,8 @@ def hashCode(): Int
8682
def toString(): String
8783
def →[B](y: B): (Object, B)
8884
final def !=(x$1: Any): Boolean
89-
final def !=(x$1: AnyRef): Boolean
9085
final def ##(): Int
9186
final def ==(x$1: Any): Boolean
92-
final def ==(x$1: AnyRef): Boolean
9387
final def asInstanceOf[T0]: T0
9488
final def eq(x$1: AnyRef): Boolean
9589
final def isInstanceOf[T0]: Boolean

test/files/presentation/ide-bug-1000531.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: CrashOnLoad.scala
33
askTypeCompletion at CrashOnLoad.scala(6,12)
44
================================================================================
55
[response] askTypeCompletion at (6,12)
6-
retrieved 120 members
6+
retrieved 118 members
77
[inaccessible] protected[package lang] def clone(): Object
88
[inaccessible] protected[package lang] def finalize(): Unit
99
[inaccessible] protected[this] def reversed: List[B]
@@ -107,10 +107,8 @@ def zipWithIndex: Iterator[(B, Int)]
107107
def zip[B](that: Iterator[B]): Iterator[(B, B)]
108108
def →[B](y: B): (java.util.Iterator[B], B)
109109
final def !=(x$1: Any): Boolean
110-
final def !=(x$1: AnyRef): Boolean
111110
final def ##(): Int
112111
final def ==(x$1: Any): Boolean
113-
final def ==(x$1: AnyRef): Boolean
114112
final def asInstanceOf[T0]: T0
115113
final def eq(x$1: AnyRef): Boolean
116114
final def isInstanceOf[T0]: Boolean

test/files/presentation/implicit-member.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: ImplicitMember.scala
33
askTypeCompletion at ImplicitMember.scala(7,7)
44
================================================================================
55
[response] askTypeCompletion at (7,7)
6-
retrieved 34 members
6+
retrieved 32 members
77
def +(other: String): String
88
def ->[B](y: B): (Implicit.type, B)
99
def ensuring(cond: Boolean): Implicit.type
@@ -17,10 +17,8 @@ def toString(): String
1717
def →[B](y: B): (Implicit.type, B)
1818
final class AppliedImplicit[A] extends AnyRef
1919
final def !=(x$1: Any): Boolean
20-
final def !=(x$1: AnyRef): Boolean
2120
final def ##(): Int
2221
final def ==(x$1: Any): Boolean
23-
final def ==(x$1: AnyRef): Boolean
2422
final def asInstanceOf[T0]: T0
2523
final def eq(x$1: AnyRef): Boolean
2624
final def isInstanceOf[T0]: Boolean

test/files/presentation/ping-pong.check

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: PingPong.scala
33
askTypeCompletion at PingPong.scala(10,23)
44
================================================================================
55
[response] askTypeCompletion at (10,23)
6-
retrieved 35 members
6+
retrieved 33 members
77
[inaccessible] private[this] val ping: Ping
88
[inaccessible] protected[package lang] def clone(): Object
99
[inaccessible] protected[package lang] def finalize(): Unit
@@ -19,10 +19,8 @@ def hashCode(): Int
1919
def poke(): Unit
2020
def →[B](y: B): (Pong, B)
2121
final def !=(x$1: Any): Boolean
22-
final def !=(x$1: AnyRef): Boolean
2322
final def ##(): Int
2423
final def ==(x$1: Any): Boolean
25-
final def ==(x$1: AnyRef): Boolean
2624
final def asInstanceOf[T0]: T0
2725
final def eq(x$1: AnyRef): Boolean
2826
final def isInstanceOf[T0]: Boolean
@@ -40,7 +38,7 @@ private[this] val name: String
4038
askTypeCompletion at PingPong.scala(19,20)
4139
================================================================================
4240
[response] askTypeCompletion at (19,20)
43-
retrieved 35 members
41+
retrieved 33 members
4442
[inaccessible] protected[package lang] def clone(): Object
4543
[inaccessible] protected[package lang] def finalize(): Unit
4644
def +(other: String): String
@@ -57,10 +55,8 @@ def name: String
5755
def poke: Unit
5856
def →[B](y: B): (Ping, B)
5957
final def !=(x$1: Any): Boolean
60-
final def !=(x$1: AnyRef): Boolean
6158
final def ##(): Int
6259
final def ==(x$1: Any): Boolean
63-
final def ==(x$1: AnyRef): Boolean
6460
final def asInstanceOf[T0]: T0
6561
final def eq(x$1: AnyRef): Boolean
6662
final def isInstanceOf[T0]: Boolean

test/files/presentation/t5708.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reload: Completions.scala
33
askTypeCompletion at Completions.scala(17,9)
44
================================================================================
55
[response] askTypeCompletion at (17,9)
6-
retrieved 39 members
6+
retrieved 37 members
77
[inaccessible] private def privateM: String
88
[inaccessible] private[this] val privateV: String
99
[inaccessible] private[this] val protectedV: String
@@ -22,10 +22,8 @@ def hashCode(): Int
2222
def toString(): String
2323
def →[B](y: B): (test.Compat.type, B)
2424
final def !=(x$1: Any): Boolean
25-
final def !=(x$1: AnyRef): Boolean
2625
final def ##(): Int
2726
final def ==(x$1: Any): Boolean
28-
final def ==(x$1: AnyRef): Boolean
2927
final def asInstanceOf[T0]: T0
3028
final def eq(x$1: AnyRef): Boolean
3129
final def isInstanceOf[T0]: Boolean

0 commit comments

Comments
 (0)