Skip to content

Commit

Permalink
Generate toString only for synthetic companions of case classes (#16890)
Browse files Browse the repository at this point in the history
Don't generate a toString method if the companion is explicitly given.
This matches Scala 2's behavior.

Fixes #16879
  • Loading branch information
odersky authored Feb 19, 2023
2 parents 3e18fee + afd499b commit 769ca3b
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,11 @@ class Namer { typer: Typer =>
res = cpy.TypeDef(modCls)(
rhs = cpy.Template(modTempl)(
derived = if (fromTempl.derived.nonEmpty) fromTempl.derived else modTempl.derived,
body = fromTempl.body ++ modTempl.body))
body = fromTempl.body.filter {
case stat: DefDef => stat.name != nme.toString_
// toString should only be generated if explicit companion is missing
case _ => true
} ++ modTempl.body))
if (fromTempl.derived.nonEmpty) {
if (modTempl.derived.nonEmpty)
report.error(em"a class and its companion cannot both have `derives` clauses", mdef.srcPos)
Expand Down
16 changes: 16 additions & 0 deletions tests/run/i16879.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait Companion:
final override def toString: String = "Companion"

case class Example(value: Int)
object Example extends Companion

case class C()
object C:
override def toString = "CC"

case class D()

@main def Test =
assert(Example.toString == "Companion")
assert(C.toString == "CC")
assert(D.toString == "D")
10 changes: 4 additions & 6 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ Schema => SemanticDB v4
Uri => Classes.scala
Text => empty
Language => Scala
Symbols => 109 entries
Symbols => 108 entries
Occurrences => 114 entries
Synthetics => 2 entries

Expand Down Expand Up @@ -504,10 +504,9 @@ classes/C4#copy$default$1(). => method copy$default$1 => Int @uncheckedVariance
classes/C4#copy(). => method copy (param x: Int): C4
classes/C4#copy().(x) => param x: Int
classes/C4#x. => val method x Int
classes/C4. => final object C4 extends Object { self: C4.type => +4 decls }
classes/C4. => final object C4 extends Object { self: C4.type => +3 decls }
classes/C4.apply(). => method apply (param x: Int): C4
classes/C4.apply().(x) => param x: Int
classes/C4.toString(). => method toString => String <: scala/Any#toString().
classes/C4.unapply(). => method unapply (param x$1: C4): C4
classes/C4.unapply().(x$1) => param x$1: C4
classes/C6# => case class C6 extends Object with Product with Serializable { self: C6 => +5 decls }
Expand Down Expand Up @@ -4559,7 +4558,7 @@ Schema => SemanticDB v4
Uri => semanticdb-Types.scala
Text => empty
Language => Scala
Symbols => 144 entries
Symbols => 143 entries
Occurrences => 228 entries
Synthetics => 1 entries

Expand All @@ -4585,10 +4584,9 @@ types/Foo#copy$default$1(). => method copy$default$1 => "abc" @uncheckedVariance
types/Foo#copy(). => method copy (param s: "abc"): Foo
types/Foo#copy().(s) => param s: "abc"
types/Foo#s. => val method s "abc"
types/Foo. => final object Foo extends Object { self: Foo.type => +6 decls }
types/Foo. => final object Foo extends Object { self: Foo.type => +5 decls }
types/Foo.apply(). => method apply (param s: "abc"): Foo
types/Foo.apply().(s) => param s: "abc"
types/Foo.toString(). => method toString => String <: scala/Any#toString().
types/Foo.unapply(). => method unapply (param x$1: Foo): Foo
types/Foo.unapply().(x$1) => param x$1: Foo
types/Foo.x. => val method x "abc" @deprecated
Expand Down

0 comments on commit 769ca3b

Please sign in to comment.