From cc5eef552feb70620f1c7ec12fb737b706ba12a6 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 30 Apr 2025 09:28:26 -0700 Subject: [PATCH 1/3] Show errors in errorless test --- .../test/dotty/tools/vulpix/ParallelTesting.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 3a2f261a8e16..e6572ec81ae3 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -947,7 +947,11 @@ trait ParallelTesting extends RunnerOrchestration: Option { if actualErrors == 0 then s"\nNo errors found when compiling neg test $testSource" - else if expectedErrors == 0 then s"\nNo errors expected/defined in $testSource -- use // error or // nopos-error" + else if expectedErrors == 0 then + s"""| + |No errors expected/defined in $testSource -- use // error or // nopos-error" + |$showErrors + |""".stripMargin.trim.linesIterator.mkString("\n", "\n", "") else if expectedErrors != actualErrors then s"""|Wrong number of errors encountered when compiling $testSource |expected: $expectedErrors, actual: $actualErrors @@ -955,8 +959,10 @@ trait ParallelTesting extends RunnerOrchestration: |${unexpected.mkString("Unexpected errors:\n", "\n", "")} |$showErrors |""".stripMargin.trim.linesIterator.mkString("\n", "\n", "") - else if hasMissingAnnotations then s"\nErrors found on incorrect row numbers when compiling $testSource\n$showErrors" - else if !errorMap.isEmpty then s"\nExpected error(s) have {=}: $errorMap" + else if hasMissingAnnotations then + s"\nErrors found on incorrect row numbers when compiling $testSource\n$showErrors" + else if !errorMap.isEmpty then + s"\nExpected error(s) have {=}: $errorMap" else null } end maybeFailureMessage From fabf3e7aa3a65cd99c7b947f8ccd2e1288e0a467 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 30 Apr 2025 09:28:46 -0700 Subject: [PATCH 2/3] Adjust message pos for enum, avoid trailing space --- .../dotty/tools/dotc/typer/RefChecks.scala | 19 ++++++++++++++++--- tests/neg/abstract-givens.check | 2 +- tests/neg/i19731.check | 2 +- tests/neg/i21335.check | 4 ++-- tests/neg/i22734.check | 8 ++++++++ tests/neg/i22734.scala | 11 +++++++++++ tests/neg/i22941.check | 2 +- 7 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 tests/neg/i22734.check create mode 100644 tests/neg/i22734.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 7037a9a986aa..328ba7a2b5a3 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -760,7 +760,9 @@ object RefChecks { def showDclAndLocation(sym: Symbol) = s"${sym.showDcl} in ${sym.owner.showLocated}" def undefined(msg: String) = - abstractClassError(false, s"${showDclAndLocation(member)} is not defined $msg") + val notdefined = s"${showDclAndLocation(member)} is not defined" + val text = if !msg.isEmpty then s"$notdefined $msg" else notdefined + abstractClassError(mustBeMixin = false, text) val underlying = member.underlyingSymbol // Give a specific error message for abstract vars based on why it fails: @@ -926,8 +928,19 @@ object RefChecks { if (abstractErrors.isEmpty) checkNoAbstractDecls(clazz) - if (abstractErrors.nonEmpty) - report.error(abstractErrorMessage, clazzNamePos) + def errorPos(cls: ClassSymbol) = + val isEnumAnonCls = // courtesy of Checking.checkEnum + cls.isAnonymousClass + && cls.owner.isTerm + && (cls.owner.flagsUNSAFE.isAllOf(EnumCase) + || ((cls.owner.name eq nme.DOLLAR_NEW) && cls.owner.flagsUNSAFE.isAllOf(Private | Synthetic))) + if isEnumAnonCls then + cls.parentSyms.head.children.filterNot(_.isClass).head.srcPos + else + clazzNamePos + + if abstractErrors.nonEmpty then + report.error(abstractErrorMessage, errorPos(clazz)) checkMemberTypesOK() checkCaseClassInheritanceInvariant() diff --git a/tests/neg/abstract-givens.check b/tests/neg/abstract-givens.check index 51f50db266c2..534ebdd4e8c0 100644 --- a/tests/neg/abstract-givens.check +++ b/tests/neg/abstract-givens.check @@ -1,7 +1,7 @@ -- Error: tests/neg/abstract-givens.scala:11:8 ------------------------------------------------------------------------- 11 | given s: [T] => T => Seq[T]: // error | ^ - |instance cannot be created, since def iterator: Iterator[A] in trait IterableOnce in package scala.collection is not defined + |instance cannot be created, since def iterator: Iterator[A] in trait IterableOnce in package scala.collection is not defined -- [E164] Declaration Error: tests/neg/abstract-givens.scala:8:8 ------------------------------------------------------- 8 | given y(using Int): String = summon[Int].toString * 22 // error | ^ diff --git a/tests/neg/i19731.check b/tests/neg/i19731.check index 5c6ef5246b1d..e5c31618c29c 100644 --- a/tests/neg/i19731.check +++ b/tests/neg/i19731.check @@ -1,7 +1,7 @@ -- 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 + | 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 | ^^ diff --git a/tests/neg/i21335.check b/tests/neg/i21335.check index ae2e09df1f61..fbd8d97e8a67 100644 --- a/tests/neg/i21335.check +++ b/tests/neg/i21335.check @@ -1,8 +1,8 @@ -- Error: tests/neg/i21335.scala:7:6 ----------------------------------------------------------------------------------- 7 |class Z1 extends Bar1 // error | ^^ - | class Z1 needs to be abstract, since override def bar(): Bar1 in trait Bar1 is not defined + | class Z1 needs to be abstract, since override def bar(): Bar1 in trait Bar1 is not defined -- Error: tests/neg/i21335.scala:12:6 ---------------------------------------------------------------------------------- 12 |class Z2 extends Bar2 // error | ^^ - | class Z2 needs to be abstract, since def bar(): Bar2 in trait Bar2 is not defined + | class Z2 needs to be abstract, since def bar(): Bar2 in trait Bar2 is not defined diff --git a/tests/neg/i22734.check b/tests/neg/i22734.check new file mode 100644 index 000000000000..52de0dea0295 --- /dev/null +++ b/tests/neg/i22734.check @@ -0,0 +1,8 @@ +-- Error: tests/neg/i22734.scala:3:7 ----------------------------------------------------------------------------------- +3 |object X extends T // error status quo + | ^ + | object creation impossible, since def item: String in trait T is not defined +-- Error: tests/neg/i22734.scala:6:7 ----------------------------------------------------------------------------------- +6 | case Empty // error + | ^ + | object creation impossible, since def item: String in class Foo is not defined diff --git a/tests/neg/i22734.scala b/tests/neg/i22734.scala new file mode 100644 index 000000000000..0a332a807324 --- /dev/null +++ b/tests/neg/i22734.scala @@ -0,0 +1,11 @@ +trait T: + def item: String +object X extends T // error status quo + +enum Foo { + case Empty // error + case NonEmpty(item: String) + case Decoy // hopefully not here + + def item: String +} diff --git a/tests/neg/i22941.check b/tests/neg/i22941.check index 81edebd098d3..97159605d9e0 100644 --- a/tests/neg/i22941.check +++ b/tests/neg/i22941.check @@ -1,4 +1,4 @@ -- Error: tests/neg/i22941.scala:4:6 ----------------------------------------------------------------------------------- 4 |class Baz extends Foo: // error | ^^^ - | class Baz needs to be abstract, since def bar: String in trait Foo is not defined + | class Baz needs to be abstract, since def bar: String in trait Foo is not defined From cf448f7f7e25cfb5f23774bf05051a3c8ff63c26 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 30 Apr 2025 12:03:06 -0700 Subject: [PATCH 3/3] Promote enum error to Checking --- .../src/dotty/tools/dotc/typer/Checking.scala | 3 +++ tests/neg/i22734.check | 17 +++++++++-------- tests/neg/i22734.scala | 6 +++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 7f52c871f9de..5790f44144a8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1573,6 +1573,9 @@ trait Checking { report.error(ClassCannotExtendEnum(cls, firstParent), cdef.srcPos) if cls.isEnumClass && !isJavaEnum then checkExistingOrdinal + if cls.isEnum && cls.is(Abstract) then + if cls.children.exists(!_.isClass) && cls.info.decls.exists(m => m.is(Deferred) && m.isTerm) then + report.error(em"enum $cls has an abstract member and an unparameterized case", cdef.srcPos) } /** Check that the firstParent for an enum case derives from the declaring enum class, if not, adds it as a parent diff --git a/tests/neg/i22734.check b/tests/neg/i22734.check index 52de0dea0295..227261765da0 100644 --- a/tests/neg/i22734.check +++ b/tests/neg/i22734.check @@ -1,8 +1,9 @@ --- Error: tests/neg/i22734.scala:3:7 ----------------------------------------------------------------------------------- -3 |object X extends T // error status quo - | ^ - | object creation impossible, since def item: String in trait T is not defined --- Error: tests/neg/i22734.scala:6:7 ----------------------------------------------------------------------------------- -6 | case Empty // error - | ^ - | object creation impossible, since def item: String in class Foo is not defined +-- Error: tests/neg/i22734.scala:5:5 ----------------------------------------------------------------------------------- + 5 |enum Foo { // error + |^ + |enum class Foo has an abstract member and an unparameterized case + 6 | case Empty // refchecks error + 7 | case NonEmpty(item: String) + 8 | case Decoy // hopefully not here + 9 | def item: String +10 |} diff --git a/tests/neg/i22734.scala b/tests/neg/i22734.scala index 0a332a807324..50ff2ba5a59f 100644 --- a/tests/neg/i22734.scala +++ b/tests/neg/i22734.scala @@ -1,9 +1,9 @@ trait T: def item: String -object X extends T // error status quo +object X extends T // refchecks error status quo -enum Foo { - case Empty // error +enum Foo { // error + case Empty // refchecks error case NonEmpty(item: String) case Decoy // hopefully not here