diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index 45606b0dbef5..040301273d56 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala @@ -419,7 +419,13 @@ class SyntheticMembers(thisPhase: DenotTransformer) { * * `@unchecked` is needed for parametric case classes. */ - def canEqualBody(that: Tree, span: Span): Tree = that.isInstance(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot, span))) + def canEqualBody(that: Tree, span: Span): Tree = { + val clazzTypeU = AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot, span)) + that.isInstance(clazzTypeU).and( + This(clazz).select(defn.Product_productPrefix) + .select(defn.Any_==) + .appliedTo(that.cast(clazzTypeU).select(defn.Product_productPrefix))) + } symbolsToSynthesize.flatMap(syntheticDefIfMissing) } diff --git a/tests/run/t13033.scala b/tests/run/t13033.scala new file mode 100644 index 000000000000..c9633677c5b8 --- /dev/null +++ b/tests/run/t13033.scala @@ -0,0 +1,24 @@ +case class C(x: Int) +class D extends C(1) { override def productPrefix = "D" } + +abstract case class C1(a: Int) +class C2(a: Int) extends C1(a) { override def productPrefix = "C2" } +class C3(a: Int) extends C1(a) { override def productPrefix = "C3" } + +case class VCC(x: Int) extends AnyVal + +object Test extends App { + val c = C(1) + assert(c != new D) + assert(c == C(1)) + assert(!c.canEqual(new D)) + + val c2 = new C2(1) + val c3 = new C3(1) + assert(c2 != c3) + assert(c2.hashCode != c3.hashCode) + assert(!c2.canEqual(c3)) + + assert(VCC(1).canEqual(VCC(1))) + assert(!VCC(1).canEqual(1)) +}