From 9a2f7da1bafc337c6b9e9325e954ae82322df781 Mon Sep 17 00:00:00 2001 From: Jean Detoeuf Date: Thu, 9 Nov 2017 08:49:42 +0100 Subject: [PATCH 1/2] New format for trait redefined final method from AnyRef error message (+tests) --- .../reporting/diagnostic/ErrorMessageID.java | 1 + .../dotc/reporting/diagnostic/messages.scala | 7 +++++++ .../src/dotty/tools/dotc/typer/RefChecks.scala | 4 ++-- .../dotc/reporting/ErrorMessagesTests.scala | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index a3cde6a9d746..b7ad3692185e 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -112,6 +112,7 @@ public enum ErrorMessageID { UndefinedNamedTypeParameterID, IllegalStartOfStatementID, TraitIsExpectedID, + TraitRedefinedFinalMethodFromAnyRefID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 70287cb8d791..7b97b3604d3f 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1916,4 +1916,11 @@ object messages { |""" } } + + case class TraitRedefinedFinalMethodFromAnyRef()(implicit ctx: Context) extends Message(TraitRedefinedFinalMethodFromAnyRefID) { + val kind = "Syntax" + val msg = "Trait cannot redefine final method from class AnyRef" + val explanation = hl"""A method was defined in a trait trying to redefine a method declared in class AnyRef. + All classes inherit from AnyRef and should not redefine its methods""" + } } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index efecb89d5d68..663953ba4082 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -116,7 +116,7 @@ object RefChecks { if (!cls.owner.is(ModuleClass)) { def clashes(sym: Symbol) = sym.isClass && - sym.name.stripModuleClassSuffix == cls.name.stripModuleClassSuffix + sym.name.stripModuleClassSuffix == cls.name.stripModuleClassSuffix val others = cls.owner.linkedClass.info.decls.filter(clashes) others.foreach { other => @@ -606,7 +606,7 @@ object RefChecks { // override a concrete method in Object. The jvm, however, does not. val overridden = decl.matchingDecl(defn.ObjectClass, defn.ObjectType) if (overridden.is(Final)) - ctx.error("trait cannot redefine final method from class AnyRef", decl.pos) + ctx.error(TraitRedefinedFinalMethodFromAnyRef(), decl.pos) } } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index e23c5089df88..325e87db92ae 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -1172,4 +1172,22 @@ class ErrorMessagesTests extends ErrorMessagesTest { val TraitIsExpected(symbol) :: Nil = messages assertEquals("class B", symbol.show) } + + @Test def traitRedefinedFinalMethodFromAnyRef = + checkMessagesAfter("refchecks") { + """ + |trait C { + | def wait (): Unit + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + + assertMessageCount(1, messages) + val err :: Nil = messages + + assertEquals(TraitRedefinedFinalMethodFromAnyRef(), err) + } + } From b0925604eae1a47c434a871f9741090813f0af5a Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Sat, 18 Nov 2017 19:44:56 +0100 Subject: [PATCH 2/2] Polish --- .../dotty/tools/dotc/reporting/diagnostic/messages.scala | 7 +++---- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 2 +- .../dotty/tools/dotc/reporting/ErrorMessagesTests.scala | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 7b97b3604d3f..be31e609fd2c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1917,10 +1917,9 @@ object messages { } } - case class TraitRedefinedFinalMethodFromAnyRef()(implicit ctx: Context) extends Message(TraitRedefinedFinalMethodFromAnyRefID) { + case class TraitRedefinedFinalMethodFromAnyRef(method: Symbol)(implicit ctx: Context) extends Message(TraitRedefinedFinalMethodFromAnyRefID) { val kind = "Syntax" - val msg = "Trait cannot redefine final method from class AnyRef" - val explanation = hl"""A method was defined in a trait trying to redefine a method declared in class AnyRef. - All classes inherit from AnyRef and should not redefine its methods""" + val msg = hl"Traits cannot redefine final $method from ${"class AnyRef"}." + val explanation = "" } } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 663953ba4082..07164bc68f8d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -606,7 +606,7 @@ object RefChecks { // override a concrete method in Object. The jvm, however, does not. val overridden = decl.matchingDecl(defn.ObjectClass, defn.ObjectType) if (overridden.is(Final)) - ctx.error(TraitRedefinedFinalMethodFromAnyRef(), decl.pos) + ctx.error(TraitRedefinedFinalMethodFromAnyRef(overridden), decl.pos) } } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 325e87db92ae..4282e5aa367d 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -1185,9 +1185,8 @@ class ErrorMessagesTests extends ErrorMessagesTest { implicit val ctx: Context = ictx assertMessageCount(1, messages) - val err :: Nil = messages - - assertEquals(TraitRedefinedFinalMethodFromAnyRef(), err) + val TraitRedefinedFinalMethodFromAnyRef(method) = messages.head + assertEquals("method wait", method.show) } }