From 1f0da4e18bf919c8011fbc5f31cf1d9c4da0f0be Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 4 Jul 2025 18:48:09 +0200 Subject: [PATCH] Fix missing members reporting for var setters Suppress reporting a missing setter only if the corresponding getter was also reported as missing. Fixes #23474 --- .../dotty/tools/dotc/typer/RefChecks.scala | 8 +++++- tests/neg/i23474.check | 25 +++++++++++++++++++ tests/neg/i23474.scala | 19 ++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i23474.check create mode 100644 tests/neg/i23474.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 9f29a15b9141..a79408b756ee 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -703,10 +703,16 @@ object RefChecks { // to consolidate getters and setters. val grouped = missing.groupBy(_.underlyingSymbol.name) + def isDuplicateSetter(sym: Symbol): Boolean = + sym.isSetter && { + val field = sym.accessedFieldOrGetter + grouped.getOrElse(field.name, Nil).contains(field) + } + val missingMethods = grouped.toList flatMap { case (name, syms) => lastOverrides(syms) - .filterConserve(!_.isSetter) + .filterConserve(!isDuplicateSetter(_)) // Avoid reporting override error for both `x` and setter `x_=` .distinctBy(_.signature) // Avoid duplication for similar definitions (#19731) } diff --git a/tests/neg/i23474.check b/tests/neg/i23474.check new file mode 100644 index 000000000000..441978be6809 --- /dev/null +++ b/tests/neg/i23474.check @@ -0,0 +1,25 @@ +-- Error: tests/neg/i23474.scala:5:11 ---------------------------------------------------------------------------------- +5 |case class Y(val comment: String) extends Comment // error + | ^ + | class Y needs to be abstract, since var comment_=(x$1: String): Unit in trait Comment is not defined + | (Note that an abstract var requires a setter in addition to the getter) +-- Error: tests/neg/i23474.scala:7:6 ----------------------------------------------------------------------------------- +7 |class Z extends Comment: // error + | ^ + | class Z needs to be abstract, since var comment_=(x$1: String): Unit in trait Comment is not defined + | (Note that an abstract var requires a setter in addition to the getter) +-- [E164] Declaration Error: tests/neg/i23474.scala:11:15 -------------------------------------------------------------- +11 | override def comment: String = "" // error + | ^ + | error overriding variable comment in trait Comment of type String; + | method comment of type => String cannot override a mutable variable +-- Error: tests/neg/i23474.scala:10:6 ---------------------------------------------------------------------------------- +10 |class X extends Comment: // error + | ^ + | class X needs to be abstract, since var comment_=(x$1: String): Unit in trait Comment is not defined + | (Note that an abstract var requires a setter in addition to the getter) +-- Error: tests/neg/i23474.scala:13:6 ---------------------------------------------------------------------------------- +13 |class W extends Comment // error + | ^ + | class W needs to be abstract, since var comment: String in trait Comment is not defined + | (Note that variables need to be initialized to be defined) diff --git a/tests/neg/i23474.scala b/tests/neg/i23474.scala new file mode 100644 index 000000000000..3e34c2f457c0 --- /dev/null +++ b/tests/neg/i23474.scala @@ -0,0 +1,19 @@ +trait Comment { + var comment: String +} + +case class Y(val comment: String) extends Comment // error + +class Z extends Comment: // error + val comment: String = "" + +class X extends Comment: // error + override def comment: String = "" // error + +class W extends Comment // error + + +class OK: + val comment: String = "" + def comment_=(x: String): Unit = () +