From 1f7789f71aea94c38aa53b4f9505c825d3c9a2d6 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 27 Feb 2024 18:25:51 +0100 Subject: [PATCH] Improve error reporting for missing members Co-Authored-By: valentin2.schneeberger@gmail.com Co-Authored-By: sana.carlo@gmail.com Co-Authored-By: mehdi.ala03@gmail.com --- .../dotty/tools/dotc/typer/RefChecks.scala | 12 ++++----- tests/neg/i19731.check | 27 +++++++++++++++++++ tests/neg/i19731.scala | 17 ++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i19731.check create mode 100644 tests/neg/i19731.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index cf30945a7751..ff44ba6d010d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -654,8 +654,8 @@ object RefChecks { val missingMethods = grouped.toList flatMap { case (name, syms) => - val withoutSetters = syms filterNot (_.isSetter) - if (withoutSetters.nonEmpty) withoutSetters else syms + syms.filterConserve(!_.isSetter) + .distinctBy(_.signature) // Avoid duplication for similar definitions (#19731) } def stubImplementations: List[String] = { @@ -666,7 +666,7 @@ object RefChecks { if (regrouped.tail.isEmpty) membersStrings(regrouped.head._2) - else (regrouped.sortBy("" + _._1.name) flatMap { + else (regrouped.sortBy(_._1.name.toString()) flatMap { case (owner, members) => ("// Members declared in " + owner.fullName) +: membersStrings(members) :+ "" }).init @@ -685,7 +685,7 @@ object RefChecks { return } - for (member <- missing) { + for (member <- missingMethods) { def showDclAndLocation(sym: Symbol) = s"${sym.showDcl} in ${sym.owner.showLocated}" def undefined(msg: String) = @@ -1002,9 +1002,9 @@ object RefChecks { end checkNoPrivateOverrides def checkVolatile(sym: Symbol)(using Context): Unit = - if sym.isVolatile && !sym.is(Mutable) then + if sym.isVolatile && !sym.is(Mutable) then report.warning(VolatileOnVal(), sym.srcPos) - + /** Check that unary method definition do not receive parameters. * They can only receive inferred parameters such as type parameters and implicit parameters. */ diff --git a/tests/neg/i19731.check b/tests/neg/i19731.check new file mode 100644 index 000000000000..eebfb924d199 --- /dev/null +++ b/tests/neg/i19731.check @@ -0,0 +1,27 @@ +-- Error: tests/neg/i19731.scala:4:6 ----------------------------------------------------------------------------------- +4 |class F1 extends Foo: // error + | ^ + | class F1 needs to be abstract, since def foo(): Unit in class F1 is not defined +-- Error: tests/neg/i19731.scala:7:6 ----------------------------------------------------------------------------------- +7 |class F2 extends Foo: // error + | ^ + | class F2 needs to be abstract, since: + | it has 2 unimplemented members. + | /** As seen from class F2, the missing signatures are as follows. + | * For convenience, these are usable as stub implementations. + | */ + | def foo(): Unit = ??? + | def foo(x: Int): Unit = ??? +-- Error: tests/neg/i19731.scala:16:6 ---------------------------------------------------------------------------------- +16 |class B1 extends Bar: // error + | ^ + | class B1 needs to be abstract, since: + | it has 2 unimplemented members. + | /** As seen from class B1, the missing signatures are as follows. + | * For convenience, these are usable as stub implementations. + | */ + | // Members declared in B1 + | def foo(x: Int): Unit = ??? + | + | // Members declared in Bar + | def foo(): Unit = ??? diff --git a/tests/neg/i19731.scala b/tests/neg/i19731.scala new file mode 100644 index 000000000000..75fff0e53872 --- /dev/null +++ b/tests/neg/i19731.scala @@ -0,0 +1,17 @@ +trait Foo: + def foo(): Unit + +class F1 extends Foo: // error + def foo(): Unit + +class F2 extends Foo: // error + def foo(): Unit + def foo(x: Int): Unit + + +trait Bar: + def foo(): Unit + def foo(x: Int): Unit + +class B1 extends Bar: // error + def foo(x: Int): Unit