Skip to content

Commit 3de42be

Browse files
committed
Revise duplicate diagnostics logic
The logic that hid duplicate messages was fragile and overly aggressive. - Because of mixin ordering, it could be that a non-sensical message that was in the end not reported could prevent a message at overlapping positions to be hidden. This could mean that no errors at all were reported even through the program was erroneous. - A message that ended up to be hidden since it overlapped with another message could still hide further messages with which it overlapped as well. Fixing the logic meant that some tests have more error messages reported. Fixes #14834 Fixes #12457
1 parent 4a96ce7 commit 3de42be

File tree

12 files changed

+39
-22
lines changed

12 files changed

+39
-22
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ abstract class Reporter extends interfaces.ReporterResult {
153153
case w: Warning if ctx.settings.XfatalWarnings.value => w.toError
154154
case _ => dia
155155
if !isHidden(d) then // avoid isHidden test for summarized warnings so that message is not forced
156+
markReported(d)
156157
withMode(Mode.Printing)(doReport(d))
157158
d match {
158159
case _: Warning => _warningCount += 1
@@ -236,6 +237,8 @@ abstract class Reporter extends interfaces.ReporterResult {
236237
def isHidden(dia: Diagnostic)(using Context): Boolean =
237238
ctx.mode.is(Mode.Printing)
238239

240+
def markReported(dia: Diagnostic)(using Context): Unit = ()
241+
239242
/** Does this reporter contain errors that have yet to be reported by its outer reporter ?
240243
* Note: this is always false when there is no outer reporter.
241244
*/

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,27 @@ trait UniqueMessagePositions extends Reporter {
1212

1313
private val positions = new mutable.HashMap[(SourceFile, Integer), Diagnostic]
1414

15+
extension (dia1: Diagnostic)
16+
private def hides(dia2: Diagnostic)(using Context): Boolean =
17+
if dia2.msg.showAlways then dia1.msg.getClass == dia2.msg.getClass
18+
else dia1.level >= dia2.level
19+
1520
/** Logs a position and returns true if it was already logged.
1621
* @note Two positions are considered identical for logging if they have the same point.
1722
*/
1823
override def isHidden(dia: Diagnostic)(using Context): Boolean =
19-
extension (dia1: Diagnostic) def hides(dia2: Diagnostic): Boolean =
20-
if dia2.msg.showAlways then dia1.msg.getClass == dia2.msg.getClass
21-
else dia1.level >= dia2.level
22-
super.isHidden(dia) || {
24+
super.isHidden(dia)
25+
||
2326
dia.pos.exists
2427
&& !ctx.settings.YshowSuppressedErrors.value
25-
&& {
26-
var shouldHide = false
27-
for (pos <- dia.pos.start to dia.pos.end)
28-
positions get (ctx.source, pos) match {
29-
case Some(dia1) if dia1.hides(dia) => shouldHide = true
30-
case _ => positions((ctx.source, pos)) = dia
31-
}
32-
shouldHide
33-
}
34-
}
28+
&& (dia.pos.start to dia.pos.end).exists(pos =>
29+
positions.get((ctx.source, pos)).exists(_.hides(dia)))
30+
31+
override def markReported(dia: Diagnostic)(using Context): Unit =
32+
if dia.pos.exists then
33+
for (pos <- dia.pos.start to dia.pos.end)
34+
positions.get(ctx.source, pos) match
35+
case Some(dia1) if dia1.hides(dia) =>
36+
case _ => positions((ctx.source, pos)) = dia
37+
super.markReported(dia)
3538
}

tests/neg-custom-args/erased/tupled-function-instances.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ object Test {
44
type T
55
type R
66

7-
summon[TupledFunction[(erased T) => R, erased Tuple1[T] => R]] // error
7+
summon[TupledFunction[(erased T) => R, erased Tuple1[T] => R]] // error // error
88
summon[TupledFunction[(erased T, T) => R, (erased (T, T)) => R]] // error
99
summon[TupledFunction[(erased T, T, T) => R,(erased (T, T, T)) => R]] // error
1010
summon[TupledFunction[(erased T, T, T, T) => R,(erased (T, T, T, T)) => R]] // error

tests/neg/i12457.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import language.`3.1-migration`
2+
3+
trait X [ X <: Z , Z >: X [ R ] ] // error

tests/neg/i14834.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type F[_] = A
2+
type A = F[?] // error: cyclic

tests/neg/i6056.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ object i0{
22
import i0.i0 // error
33
def i0={
44
import _ // error
5-
import
5+
import // error
66
} // error
77
}

tests/neg/i7818.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
def foo = (x: @) => () // error
1+
def foo = (x: @) => () // error // error

tests/neg/i9328.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Foo2[T <: Id[T]] // error // error
77

88
object Foo { // error
99
object Foo { }
10-
Foo { }
10+
Foo { } // error
1111
}
1212
implicit class Foo(a: Float) // error
1313
case class Foo()

tests/neg/parser-stability-17.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
trait x0[] { x0: x0 => } // error // error
2-
class x0[x1] extends x0[x0 x0] x2 x0 // error // error
2+
class x0[x1] extends x0[x0 x0] x2 x0 // error // error // error

tests/neg/parser-stability-9.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import
1+
import // error
22
// error

tests/neg/t5702-neg-bad-and-wild.check

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
|
2828
| longer explanation available when compiling with `-explain`
2929
-- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:23:17 ---------------------------------------------------
30-
23 | val K(ns @ _*, xx) = k // error: pattern expected
30+
23 | val K(ns @ _*, xx) = k // error: pattern expected // error
3131
| ^
3232
| pattern expected
3333
|
@@ -50,3 +50,9 @@
5050
| Not found: *
5151
|
5252
| longer explanation available when compiling with `-explain`
53+
-- [E045] Cyclic Error: tests/neg/t5702-neg-bad-and-wild.scala:23:19 ---------------------------------------------------
54+
23 | val K(ns @ _*, xx) = k // error: pattern expected // error
55+
| ^
56+
| Recursive value $1$ needs type
57+
|
58+
| longer explanation available when compiling with `-explain`

tests/neg/t5702-neg-bad-and-wild.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object Test {
2020
// good syntax, bad semantics, detected by typer
2121
//gowild.scala:14: error: star patterns must correspond with varargs parameters
2222
val K(x @ _*) = k
23-
val K(ns @ _*, xx) = k // error: pattern expected
23+
val K(ns @ _*, xx) = k // error: pattern expected // error
2424
val K(x) = k // error: x is already defined as value x
2525
val (b, _ * ) = (5,6) // ok
2626
// no longer complains

0 commit comments

Comments
 (0)