Skip to content

Commit

Permalink
Merge pull request scala#3497 from adriaanm/rebase-3464
Browse files Browse the repository at this point in the history
 Make Object#== override Any#==
  • Loading branch information
adriaanm committed Feb 10, 2014
2 parents c611f7b + 127a767 commit 59fc37a
Show file tree
Hide file tree
Showing 18 changed files with 114 additions and 59 deletions.
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Infer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ trait Infer extends Checkable {
private lazy val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)

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

/* -- Error Messages --------------------------------------------------- */
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper

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

val infer = new Inferencer(context0) {
val infer = new Inferencer {
def context = Typer.this.context
// See SI-3281 re undoLog
override def isCoercible(tp: Type, pt: Type) = undoLog undo viewExists(tp, pt)
}
Expand Down
4 changes: 2 additions & 2 deletions src/library-aux/scala/AnyRef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ trait AnyRef extends Any {
* @param arg0 the object to compare against this object for equality.
* @return `true` if the receiver object is equivalent to the argument; `false` otherwise.
*/
final def ==(that: AnyRef): Boolean =
if (this eq null) that eq null
final def ==(that: Any): Boolean =
if (this eq null) that.asInstanceOf[AnyRef] eq null
else this equals that

/** Create a copy of the receiver object.
Expand Down
13 changes: 10 additions & 3 deletions src/reflect/scala/reflect/internal/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ trait Definitions extends api.StandardDefinitions {
private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long): MethodSymbol = {
val msym = owner.newMethod(name.encode, NoPosition, flags)
val params = msym.newSyntheticValueParams(formals)
msym setInfo MethodType(params, restpe) markAllCompleted
val info = if (owner.isJavaDefined) JavaMethodType(params, restpe) else MethodType(params, restpe)
msym setInfo info markAllCompleted
}
private def enterNewMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): MethodSymbol =
owner.info.decls enter newMethod(owner, name, formals, restpe, flags)
Expand Down Expand Up @@ -904,8 +905,14 @@ trait Definitions extends api.StandardDefinitions {
existentialAbstraction(clazz.unsafeTypeParams, clazz.tpe_*)

// members of class scala.Any

// TODO these aren't final! They are now overriden in AnyRef/Object. Prior to the fix
// for SI-8129, they were actually *overloaded* by the members in AnyRef/Object.
// We should unfinalize these, override in AnyValClass, and make the overrides final.
// Refchecks never actually looks at these, so its just for consistency.
lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL)
lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL)

lazy val Any_equals = enterNewMethod(AnyClass, nme.equals_, AnyTpe :: Nil, BooleanTpe)
lazy val Any_hashCode = enterNewMethod(AnyClass, nme.hashCode_, Nil, IntTpe)
lazy val Any_toString = enterNewMethod(AnyClass, nme.toString_, Nil, StringTpe)
Expand Down Expand Up @@ -1012,8 +1019,8 @@ trait Definitions extends api.StandardDefinitions {

// members of class java.lang.{ Object, String }
lazy val Object_## = enterNewMethod(ObjectClass, nme.HASHHASH, Nil, IntTpe, FINAL)
lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, AnyRefTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, AnyRefTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, AnyRefTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, AnyRefTpe :: Nil, BooleanTpe, FINAL)
lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_ => BooleanTpe)
Expand Down
10 changes: 10 additions & 0 deletions test/files/neg/t8219-any-any-ref-equals.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
t8219-any-any-ref-equals.scala:5: error: method ==: (x$1: Any)Boolean does not take type parameters.
"".==[Int]
^
t8219-any-any-ref-equals.scala:6: error: method ==: (x$1: Any)Boolean does not take type parameters.
("": AnyRef).==[Int]
^
t8219-any-any-ref-equals.scala:7: error: method ==: (x$1: Any)Boolean does not take type parameters.
("": Object).==[Int]
^
three errors found
8 changes: 8 additions & 0 deletions test/files/neg/t8219-any-any-ref-equals.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
object Test {
// The error message tells us that AnyRef#== and Any#== are overloaded.
// A real class couldn't define such an overload, why do we allow AnyRef
// to do so?
"".==[Int]
("": AnyRef).==[Int]
("": Object).==[Int]
}
15 changes: 15 additions & 0 deletions test/files/pos/t8219.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
trait Equalizer[T]
trait Gen[A]

class Broken {
implicit def const[T](x: T): Gen[T] = ???
implicit def convertToEqualizer[T](left: T): Equalizer[T] = ???

def in(a: Any) = ()
in {
import scala.None // any import will do..
"" == "" // this no longer triggers the bug, as Object#== now overrides Any#==
}

// We can still trigger the bug with a structural type, see pending/neg/t8219.scala
}
49 changes: 49 additions & 0 deletions test/files/pos/t8219b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
trait Equalizer[T]
trait Gen[A]

class Broken {
implicit def const[T](x: T): Gen[T] = ???
implicit def convertToEqualizer[T](left: T): Equalizer[T] = ???

def in(a: Any) = ()
in {
import scala.None // any import will do..
"" == "" // no longer a problem, see pos/t8129.scala
}

// We used to fall into the errant code path above when `Any#==` and `AnyRef#==`
// were overloaded.
//
// Real classes couldn't get away with that overloading; it would result in
// a compiler error because the variants would collapse into an overriding
// relationship after erasure.
//
//
// But, a structural type can! This triggers the same error, and served as
// a backstop for this test if we change the signatures of `AnyRef#==` to
// override `Any#==`.
type T = {
def a(a: AnyRef): Boolean
def a(a: Any): Boolean
}

def t: T = ???

in {
import scala.None // any import will do..
t.a("")
}

// Or, we can get here with ambiguous implicits from the formal parameter
// type of the less specific overload to that of the more specific.
object T {
def foo(a: Any) = true
def foo(a: String) = true
}
in {
import scala.None
implicit def any2str1(a: Any) = ""
implicit def any2str2(a: Any) = ""
T.foo("")
}
}
4 changes: 1 addition & 3 deletions test/files/presentation/callcc-interpreter.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: CallccInterpreter.scala
askTypeCompletion at CallccInterpreter.scala(51,34)
================================================================================
[response] askTypeCompletion at (51,34)
retrieved 59 members
retrieved 57 members
abstract trait Term extends AnyRef
abstract trait Value extends AnyRef
case class Add extends callccInterpreter.Term with Product with Serializable
Expand Down Expand Up @@ -38,10 +38,8 @@ def toString(): String
def unitM[A](a: A): callccInterpreter.M[A]
def →[B](y: B): (callccInterpreter.type, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
4 changes: 1 addition & 3 deletions test/files/presentation/completion-implicit-chained.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@ reload: Completions.scala
askTypeCompletion at Completions.scala(11,16)
================================================================================
[response] askTypeCompletion at (11,16)
retrieved 24 members
retrieved 22 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
def equals(x$1: Any): Boolean
def hashCode(): Int
def map(x: Int => Int)(implicit a: DummyImplicit): test.O.type
def toString(): String
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
4 changes: 1 addition & 3 deletions test/files/presentation/ide-bug-1000349.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: CompletionOnEmptyArgMethod.scala
askTypeCompletion at CompletionOnEmptyArgMethod.scala(2,17)
================================================================================
[response] askTypeCompletion at (2,17)
retrieved 32 members
retrieved 30 members
def +(other: String): String
def ->[B](y: B): (Foo, B)
def ensuring(cond: Boolean): Foo
Expand All @@ -17,10 +17,8 @@ def hashCode(): Int
def toString(): String
def →[B](y: B): (Foo, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
12 changes: 3 additions & 9 deletions test/files/presentation/ide-bug-1000475.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: Foo.scala
askTypeCompletion at Foo.scala(3,7)
================================================================================
[response] askTypeCompletion at (3,7)
retrieved 31 members
retrieved 29 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
def +(other: String): String
Expand All @@ -18,10 +18,8 @@ def hashCode(): Int
def toString(): String
def →[B](y: B): (Object, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand All @@ -37,7 +35,7 @@ final def wait(x$1: Long,x$2: Int): Unit
askTypeCompletion at Foo.scala(6,10)
================================================================================
[response] askTypeCompletion at (6,10)
retrieved 31 members
retrieved 29 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
def +(other: String): String
Expand All @@ -52,10 +50,8 @@ def hashCode(): Int
def toString(): String
def →[B](y: B): (Object, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand All @@ -71,7 +67,7 @@ final def wait(x$1: Long,x$2: Int): Unit
askTypeCompletion at Foo.scala(7,7)
================================================================================
[response] askTypeCompletion at (7,7)
retrieved 31 members
retrieved 29 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
def +(other: String): String
Expand All @@ -86,10 +82,8 @@ def hashCode(): Int
def toString(): String
def →[B](y: B): (Object, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
4 changes: 1 addition & 3 deletions test/files/presentation/ide-bug-1000531.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: CrashOnLoad.scala
askTypeCompletion at CrashOnLoad.scala(6,12)
================================================================================
[response] askTypeCompletion at (6,12)
retrieved 120 members
retrieved 118 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
[inaccessible] protected[this] def reversed: List[B]
Expand Down Expand Up @@ -107,10 +107,8 @@ def zipWithIndex: Iterator[(B, Int)]
def zip[B](that: Iterator[B]): Iterator[(B, B)]
def →[B](y: B): (java.util.Iterator[B], B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
4 changes: 1 addition & 3 deletions test/files/presentation/implicit-member.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: ImplicitMember.scala
askTypeCompletion at ImplicitMember.scala(7,7)
================================================================================
[response] askTypeCompletion at (7,7)
retrieved 34 members
retrieved 32 members
def +(other: String): String
def ->[B](y: B): (Implicit.type, B)
def ensuring(cond: Boolean): Implicit.type
Expand All @@ -17,10 +17,8 @@ def toString(): String
def →[B](y: B): (Implicit.type, B)
final class AppliedImplicit[A] extends AnyRef
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
8 changes: 2 additions & 6 deletions test/files/presentation/ping-pong.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: PingPong.scala
askTypeCompletion at PingPong.scala(10,23)
================================================================================
[response] askTypeCompletion at (10,23)
retrieved 35 members
retrieved 33 members
[inaccessible] private[this] val ping: Ping
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
Expand All @@ -19,10 +19,8 @@ def hashCode(): Int
def poke(): Unit
def →[B](y: B): (Pong, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand All @@ -40,7 +38,7 @@ private[this] val name: String
askTypeCompletion at PingPong.scala(19,20)
================================================================================
[response] askTypeCompletion at (19,20)
retrieved 35 members
retrieved 33 members
[inaccessible] protected[package lang] def clone(): Object
[inaccessible] protected[package lang] def finalize(): Unit
def +(other: String): String
Expand All @@ -57,10 +55,8 @@ def name: String
def poke: Unit
def →[B](y: B): (Ping, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
4 changes: 1 addition & 3 deletions test/files/presentation/t5708.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reload: Completions.scala
askTypeCompletion at Completions.scala(17,9)
================================================================================
[response] askTypeCompletion at (17,9)
retrieved 39 members
retrieved 37 members
[inaccessible] private def privateM: String
[inaccessible] private[this] val privateV: String
[inaccessible] private[this] val protectedV: String
Expand All @@ -22,10 +22,8 @@ def hashCode(): Int
def toString(): String
def →[B](y: B): (test.Compat.type, B)
final def !=(x$1: Any): Boolean
final def !=(x$1: AnyRef): Boolean
final def ##(): Int
final def ==(x$1: Any): Boolean
final def ==(x$1: AnyRef): Boolean
final def asInstanceOf[T0]: T0
final def eq(x$1: AnyRef): Boolean
final def isInstanceOf[T0]: Boolean
Expand Down
Loading

0 comments on commit 59fc37a

Please sign in to comment.