From 4b539659adda7176db10fe2208b44d0198ea5657 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 12a53a19931d..ecda82e14da6 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -945,7 +945,11 @@ trait ParallelTesting extends RunnerOrchestration { self => 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 @@ -953,8 +957,10 @@ trait ParallelTesting extends RunnerOrchestration { self => |${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 0ee6e7262449b3185a8c366b97e5cdad3df089d7 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 +++++++++++ 6 files changed, 39 insertions(+), 7 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 f81c1bf19cb1..1d48ee5bd7df 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -790,7 +790,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: @@ -956,8 +958,19 @@ object RefChecks { if (abstractErrors.isEmpty) checkNoAbstractDecls(clazz) - if (abstractErrors.nonEmpty) - report.error(abstractErrorMessage, clazz.srcPos) + 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 + cls.srcPos + + 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 1430c5b6e950..b4cc1fede296 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 eebfb924d199..fb62614f65ac 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 a7ee092eec0e..fe62218eaa5a 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 +} From 9b3d4a1d71147fd99bc00bd4b0f270eb30d2610d 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 cc43e950ec10..977b82012f2f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1486,6 +1486,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