Skip to content

Commit fbdf7c6

Browse files
committed
Unsuppress unchecked warnings
And check it with a pos checkfile.
1 parent c5adafc commit fbdf7c6

File tree

8 files changed

+151
-89
lines changed

8 files changed

+151
-89
lines changed

compiler/src/dotty/tools/dotc/reporting/Message.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ abstract class Message(val errorId: ErrorMessageID)(using Context) { self =>
408408
override def canExplain = true
409409

410410
/** Override with `true` for messages that should always be shown even if their
411-
* position overlaps another messsage of a different class. On the other hand
411+
* position overlaps another message of a different class. On the other hand
412412
* multiple messages of the same class with overlapping positions will lead
413413
* to only a single message of that class to be issued.
414414
*/

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,10 @@ extends Message(PatternMatchExhaustivityID) {
895895
}
896896
}
897897

898-
class UncheckedTypePattern(msgFn: => String)(using Context)
898+
class UncheckedTypePattern(argType: Type, whyNot: String)(using Context)
899899
extends PatternMatchMsg(UncheckedTypePatternID) {
900-
def msg(using Context) = msgFn
900+
override def showAlways = true
901+
def msg(using Context) = i"the type test for $argType cannot be checked at runtime because $whyNot"
901902
def explain(using Context) =
902903
i"""|Type arguments and type refinements are erased during compile time, thus it's
903904
|impossible to check them at run-time.

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ object TypeTestsCasts {
363363
if !isTrusted && !isUnchecked then
364364
val whyNot = whyUncheckable(expr.tpe, argType, tree.span)
365365
if whyNot.nonEmpty then
366-
report.uncheckedWarning(em"the type test for $argType cannot be checked at runtime because $whyNot", expr.srcPos)
366+
report.uncheckedWarning(UncheckedTypePattern(argType, whyNot), expr.srcPos)
367367
transformTypeTest(expr, argType,
368368
flagUnrelated = enclosingInlineds.isEmpty) // if test comes from inlined code, dont't flag it even if it always false
369369
}

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ class CompilationTests {
134134
).times(2).checkCompile()
135135
}
136136

137+
// Warning tests ------------------------------------------------------------
138+
139+
@Test def warn: Unit = {
140+
implicit val testGroup: TestGroup = TestGroup("compileWarn")
141+
aggregateTests(
142+
compileFilesInDir("tests/warn", defaultOptions),
143+
).checkWarnings()
144+
}
145+
137146
// Negative tests ------------------------------------------------------------
138147

139148
@Test def negAll: Unit = {

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
226226
Try(testSource match {
227227
case testSource @ JointCompilationSource(name, files, flags, outDir, fromTasty, decompilation) =>
228228
val reporter =
229-
if (fromTasty) compileFromTasty(flags, suppressErrors, outDir)
230-
else compile(testSource.sourceFiles, flags, suppressErrors, outDir)
229+
if (fromTasty) compileFromTasty(flags, outDir)
230+
else compile(testSource.sourceFiles, flags, outDir)
231231
List(reporter)
232232

233233
case testSource @ SeparateCompilationSource(_, dir, flags, outDir) =>
234234
testSource.compilationGroups.map { (group, files) =>
235235
if group.compiler.isEmpty then
236-
compile(files, flags, suppressErrors, outDir)
236+
compile(files, flags, outDir)
237237
else
238238
compileWithOtherCompiler(group.compiler, files, flags, outDir)
239239
}
@@ -469,7 +469,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
469469
registerCompletion()
470470
throw e
471471

472-
protected def compile(files0: Array[JFile], flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = {
472+
protected def compile(files0: Array[JFile], flags0: TestFlags, targetDir: JFile): TestReporter = {
473473
import scala.util.Properties.*
474474

475475
def flattenFiles(f: JFile): Array[JFile] =
@@ -634,7 +634,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
634634

635635
reporter
636636

637-
protected def compileFromTasty(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = {
637+
protected def compileFromTasty(flags0: TestFlags, targetDir: JFile): TestReporter = {
638638
val tastyOutput = new JFile(targetDir.getPath + "_from-tasty")
639639
tastyOutput.mkdir()
640640
val flags = flags0 and ("-d", tastyOutput.getPath) and "-from-tasty"
@@ -653,6 +653,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
653653
private def mkLogLevel = if suppressErrors || suppressAllOutput then ERROR + 1 else ERROR
654654
private def mkReporter = TestReporter.reporter(realStdout, logLevel = mkLogLevel)
655655

656+
protected def diffCheckfile(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable) =
657+
checkFile(testSource).foreach(diffTest(testSource, _, reporterOutputLines(reporters), reporters, logger))
658+
659+
private def reporterOutputLines(reporters: Seq[TestReporter]): List[String] =
660+
reporters.flatMap(_.consoleOutput.split("\n")).toList
661+
656662
private[ParallelTesting] def executeTestSuite(): this.type = {
657663
assert(testSourcesCompleted == 0, "not allowed to re-use a `CompileRun`")
658664
if filteredSources.nonEmpty then
@@ -717,6 +723,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
717723
private final class PosTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting)
718724
extends Test(testSources, times, threadLimit, suppressAllOutput)
719725

726+
private final class WarnTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting)
727+
extends Test(testSources, times, threadLimit, suppressAllOutput):
728+
override def suppressErrors = true
729+
override def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit =
730+
diffCheckfile(testSource, reporters, logger)
731+
720732
private final class RewriteTest(testSources: List[TestSource], checkFiles: Map[JFile, JFile], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting)
721733
extends Test(testSources, times, threadLimit, suppressAllOutput) {
722734
private def verifyOutput(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable) = {
@@ -808,10 +820,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
808820
end maybeFailureMessage
809821

810822
override def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit =
811-
checkFile(testSource).foreach(diffTest(testSource, _, reporterOutputLines(reporters), reporters, logger))
812-
813-
def reporterOutputLines(reporters: Seq[TestReporter]): List[String] =
814-
reporters.flatMap(_.consoleOutput.split("\n")).toList
823+
diffCheckfile(testSource, reporters, logger)
815824

816825
// In neg-tests we allow two or three types of error annotations.
817826
// Normally, `// error` must be annotated on the correct line number.
@@ -1014,20 +1023,11 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10141023
* compilation without generating errors and that they do not crash the
10151024
* compiler
10161025
*/
1017-
def checkCompile()(implicit summaryReport: SummaryReporting): this.type = {
1018-
val test = new PosTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
1019-
1020-
cleanup()
1021-
1022-
if (!shouldFail && test.didFail) {
1023-
fail(s"Expected no errors when compiling, failed for the following reason(s):\n${reasonsForFailure(test)}\n")
1024-
}
1025-
else if (shouldFail && !test.didFail && test.skipCount == 0) {
1026-
fail("Pos test should have failed, but didn't")
1027-
}
1026+
def checkCompile()(implicit summaryReport: SummaryReporting): this.type =
1027+
checkPass(new PosTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput), "Pos")
10281028

1029-
this
1030-
}
1029+
def checkWarnings()(implicit summaryReport: SummaryReporting): this.type =
1030+
checkPass(new WarnTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput), "Warn")
10311031

10321032
/** Creates a "neg" test run, which makes sure that each test generates the
10331033
* correct number of errors at the correct positions. It also makes sure
@@ -1047,35 +1047,16 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10471047
end checkExpectedErrors
10481048

10491049
/** Creates a "fuzzy" test run, which makes sure that each test compiles (or not) without crashing */
1050-
def checkNoCrash()(implicit summaryReport: SummaryReporting): this.type = {
1051-
val test = new NoCrashTest(targets, times, threadLimit, shouldSuppressOutput).executeTestSuite()
1052-
1053-
cleanup()
1054-
1055-
if (test.didFail) {
1056-
fail("Fuzzy test shouldn't have crashed, but did")
1057-
}
1058-
1059-
this
1060-
}
1050+
def checkNoCrash()(implicit summaryReport: SummaryReporting): this.type =
1051+
checkFail(new NoCrashTest(targets, times, threadLimit, shouldSuppressOutput), "Fuzzy")
10611052

10621053
/** Creates a "run" test run, which is a superset of "pos". In addition to
10631054
* making sure that all tests pass compilation and that they do not crash
10641055
* the compiler; it also makes sure that all tests can run with the
10651056
* expected output
10661057
*/
1067-
def checkRuns()(implicit summaryReport: SummaryReporting): this.type = {
1068-
val test = new RunTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
1069-
1070-
cleanup()
1071-
1072-
if !shouldFail && test.didFail then
1073-
fail(s"Run test failed, but should not, reasons:\n${ reasonsForFailure(test) }")
1074-
else if shouldFail && !test.didFail && test.skipCount == 0 then
1075-
fail("Run test should have failed, but did not")
1076-
1077-
this
1078-
}
1058+
def checkRuns()(implicit summaryReport: SummaryReporting): this.type =
1059+
checkPass(new RunTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput), "Run")
10791060

10801061
/** Tests `-rewrite`, which makes sure that the rewritten files still compile
10811062
* and agree with the expected result (if specified).
@@ -1100,15 +1081,34 @@ trait ParallelTesting extends RunnerOrchestration { self =>
11001081
target.copy(dir = copyToDir(outDir, dir))
11011082
}
11021083

1103-
val test = new RewriteTest(copiedTargets, checkFileMap, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
1084+
val test = new RewriteTest(copiedTargets, checkFileMap, times, threadLimit, shouldFail || shouldSuppressOutput)
1085+
1086+
checkFail(test, "Rewrite")
1087+
}
1088+
1089+
private def checkPass(test: Test, desc: String): this.type =
1090+
test.executeTestSuite()
11041091

11051092
cleanup()
11061093

1107-
if test.didFail then
1108-
fail("Rewrite test failed")
1094+
if !shouldFail && test.didFail then
1095+
fail(s"$desc test failed, but should not, reasons:\n${reasonsForFailure(test)}")
1096+
else if shouldFail && !test.didFail && test.skipCount == 0 then
1097+
fail(s"$desc test should have failed, but didn't")
1098+
1099+
this
1100+
1101+
private def checkFail(test: Test, desc: String): this.type =
1102+
test.executeTestSuite()
1103+
1104+
cleanup()
1105+
1106+
if shouldFail && !test.didFail && test.skipCount == 0 then
1107+
fail(s"$desc test shouldn't have failed, but did. Reasons:\n${reasonsForFailure(test)}")
1108+
else if !shouldFail && test.didFail then
1109+
fail(s"$desc test failed")
11091110

11101111
this
1111-
}
11121112

11131113
/** Deletes output directories and files */
11141114
private def cleanup(): this.type = {

tests/pending/neg/i16451.check

Lines changed: 0 additions & 24 deletions
This file was deleted.

tests/warn/i16451.check

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
-- [E029] Pattern Match Exhaustivity Warning: tests/warn/i16451.scala:12:73 --------------------------------------------
2+
12 | def test_correct(x: Wrapper[Color]): Option[Wrapper[Color.Red.type]] = x match // error: inexhaustive
3+
| ^
4+
| match may not be exhaustive.
5+
|
6+
| It would fail on pattern case: Wrapper(_)
7+
|
8+
| longer explanation available when compiling with `-explain`
9+
-- [E030] Match case Unreachable Warning: tests/warn/i16451.scala:25:9 -------------------------------------------------
10+
25 | case x: Wrapper[Color.Red.type] => Some(x) // error: unreachable // error: unchecked
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
| Unreachable case
13+
-- [E030] Match case Unreachable Warning: tests/warn/i16451.scala:29:9 -------------------------------------------------
14+
29 | case x: Wrapper[Color.Red.type] => Some(x) // error: unreachable // error: unchecked
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
| Unreachable case
17+
-- [E030] Match case Unreachable Warning: tests/warn/i16451.scala:34:11 ------------------------------------------------
18+
34 | case x: Wrapper[Color.Red.type] => x // error: unreachable // error: unchecked
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
| Unreachable case
21+
-- [E030] Match case Unreachable Warning: tests/warn/i16451.scala:39:11 ------------------------------------------------
22+
39 | case x: Wrapper[Color.Red.type] => x // error: unreachable // error: unchecked
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
| Unreachable case
25+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:13:9 ------------------------------------------------
26+
13 | case x: Wrapper[Color.Red.type] => Some(x) // error: unchecked
27+
| ^
28+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from Wrapper[Color]
29+
|
30+
| longer explanation available when compiling with `-explain`
31+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:14:9 ------------------------------------------------
32+
14 | case x: Wrapper[Color.Green.type] => None // error: unchecked
33+
| ^
34+
|the type test for Wrapper[(Color.Green : Color)] cannot be checked at runtime because its type arguments can't be determined from Wrapper[Color]
35+
|
36+
| longer explanation available when compiling with `-explain`
37+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:21:9 ------------------------------------------------
38+
21 | case x: Wrapper[Color.Red.type] => Some(x) // error: unchecked
39+
| ^
40+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from Any
41+
|
42+
| longer explanation available when compiling with `-explain`
43+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:22:9 ------------------------------------------------
44+
22 | case x: Wrapper[Color.Green.type] => None // error: unchecked
45+
| ^
46+
|the type test for Wrapper[(Color.Green : Color)] cannot be checked at runtime because its type arguments can't be determined from Any
47+
|
48+
| longer explanation available when compiling with `-explain`
49+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:25:9 ------------------------------------------------
50+
25 | case x: Wrapper[Color.Red.type] => Some(x) // error: unreachable // error: unchecked
51+
| ^
52+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from Wrapper[Color]
53+
|
54+
| longer explanation available when compiling with `-explain`
55+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:29:9 ------------------------------------------------
56+
29 | case x: Wrapper[Color.Red.type] => Some(x) // error: unreachable // error: unchecked
57+
| ^
58+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from A1
59+
|
60+
| longer explanation available when compiling with `-explain`
61+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:34:11 -----------------------------------------------
62+
34 | case x: Wrapper[Color.Red.type] => x // error: unreachable // error: unchecked
63+
| ^
64+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from Wrapper[Color]
65+
|
66+
| longer explanation available when compiling with `-explain`
67+
-- [E092] Pattern Match Unchecked Warning: tests/warn/i16451.scala:39:11 -----------------------------------------------
68+
39 | case x: Wrapper[Color.Red.type] => x // error: unreachable // error: unchecked
69+
| ^
70+
|the type test for Wrapper[(Color.Red : Color)] cannot be checked at runtime because its type arguments can't be determined from Wrapper[Color]
71+
|
72+
| longer explanation available when compiling with `-explain`

0 commit comments

Comments
 (0)