Skip to content

Commit e2ec1bf

Browse files
committed
Add fields sorting (primitives first) in case class equals
1 parent 909f10a commit e2ec1bf

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
161161
val thatAsClazz = ctx.newSymbol(ctx.owner, nme.x_0, Synthetic, clazzType, coord = ctx.owner.pos) // x$0
162162
def wildcardAscription(tp: Type) = Typed(Underscore(tp), TypeTree(tp))
163163
val pattern = Bind(thatAsClazz, wildcardAscription(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))) // x$0 @ (_: C @unchecked)
164-
val comparisons = accessors map { accessor =>
164+
// compare primitive fields first, slow equality checks of non-primitive fields can be skipped when primitives differ
165+
val sortedAccessors = accessors.sortBy(accessor => if (accessor.info.typeSymbol.isPrimitiveValueClass) 0 else 1)
166+
val comparisons = sortedAccessors.map { accessor =>
165167
This(clazz).select(accessor).equal(ref(thatAsClazz).select(accessor)) }
166168
val rhs = // this.x == this$0.x && this.y == x$0.y
167169
if (comparisons.isEmpty) Literal(Constant(true)) else comparisons.reduceLeft(_ and _)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
class X { override def equals(x: Any) = throw new Exception("shouldn't be called") }
4+
case class C(x: X, i: Int)
5+
val x = new X
6+
7+
C(x, 1) == C(x, 2)
8+
}
9+
}

0 commit comments

Comments
 (0)