Skip to content

Commit a377c8a

Browse files
authored
Suppress spurious Suppression (#22383)
Guard against multiple registrations of nowarn on related elements. Fixes #18341
1 parent bd699fc commit a377c8a

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

Diff for: compiler/src/dotty/tools/dotc/Run.scala

+10-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import StdNames.nme
3030
import java.io.{BufferedWriter, OutputStreamWriter}
3131
import java.nio.charset.StandardCharsets
3232

33-
import scala.collection.mutable
33+
import scala.collection.mutable, mutable.ListBuffer
3434
import scala.util.control.NonFatal
3535
import scala.io.Codec
3636

@@ -69,7 +69,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
6969
private var myFiles: Set[AbstractFile] = uninitialized
7070

7171
// `@nowarn` annotations by source file, populated during typer
72-
private val mySuppressions: mutable.LinkedHashMap[SourceFile, mutable.ListBuffer[Suppression]] = mutable.LinkedHashMap.empty
72+
private val mySuppressions: mutable.LinkedHashMap[SourceFile, ListBuffer[Suppression]] = mutable.LinkedHashMap.empty
7373
// source files whose `@nowarn` annotations are processed
7474
private val mySuppressionsComplete: mutable.Set[SourceFile] = mutable.Set.empty
7575
// warnings issued before a source file's `@nowarn` annotations are processed, suspended so that `@nowarn` can filter them
@@ -99,8 +99,9 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
9999
}
100100

101101
def addSuppression(sup: Suppression): Unit =
102-
val source = sup.annotPos.source
103-
mySuppressions.getOrElseUpdate(source, mutable.ListBuffer.empty) += sup
102+
val suppressions = mySuppressions.getOrElseUpdate(sup.annotPos.source, ListBuffer.empty)
103+
if sup.start != sup.end && suppressions.forall(x => x.start != sup.start || x.end != sup.end) then
104+
suppressions += sup
104105

105106
def reportSuspendedMessages(source: SourceFile)(using Context): Unit = {
106107
// sort suppressions. they are not added in any particular order because of lazy type completion
@@ -115,11 +116,12 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
115116
mySuspendedMessages.keysIterator.toList.foreach(reportSuspendedMessages)
116117
// report unused nowarns only if all all phases are done
117118
if !hasErrors && ctx.settings.WunusedHas.nowarn then
118-
for {
119+
for
119120
source <- mySuppressions.keysIterator.toList
120121
sups <- mySuppressions.remove(source)
121122
sup <- sups.reverse
122-
} if (!sup.used)
123+
if !sup.used
124+
do
123125
report.warning("@nowarn annotation does not suppress any warnings", sup.annotPos)
124126

125127
/** The compilation units currently being compiled, this may return different
@@ -130,7 +132,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
130132
private def units_=(us: List[CompilationUnit]): Unit =
131133
myUnits = us
132134

133-
var suspendedUnits: mutable.ListBuffer[CompilationUnit] = mutable.ListBuffer()
135+
var suspendedUnits: ListBuffer[CompilationUnit] = ListBuffer.empty
134136
var suspendedHints: mutable.Map[CompilationUnit, (String, Boolean)] = mutable.HashMap()
135137

136138
/** Were any units suspended in the typer phase? if so then pipeline tasty can not complete. */
@@ -172,7 +174,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
172174
val staticRefs = util.EqHashMap[Name, Denotation](initialCapacity = 1024)
173175

174176
/** Actions that need to be performed at the end of the current compilation run */
175-
private var finalizeActions = mutable.ListBuffer[() => Unit]()
177+
private var finalizeActions = ListBuffer.empty[() => Unit]
176178

177179
private var _progress: Progress | Null = null // Set if progress reporting is enabled
178180

Diff for: compiler/src/dotty/tools/dotc/reporting/WConf.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ object WConf:
134134
if (parseErrorss.nonEmpty) Left(parseErrorss.flatten)
135135
else Right(WConf(configs))
136136

137-
class Suppression(val annotPos: SourcePosition, filters: List[MessageFilter], val start: Int, end: Int, val verbose: Boolean):
137+
class Suppression(val annotPos: SourcePosition, filters: List[MessageFilter], val start: Int, val end: Int, val verbose: Boolean):
138138
private var _used = false
139139
def used: Boolean = _used
140140
def markUsed(): Unit = { _used = true }

Diff for: tests/warn/i18341.scala

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
//> using options -Wunused:params,nowarn
3+
4+
import annotation.*
5+
6+
class B(@nowarn useless: Int)
7+
8+
class C(@nowarn("msg=unused") useless: Int)
9+
10+
class D(useless: Int) // warn
11+
12+
class E(@nowarn useful: Int): // warn
13+
def e = useful * 10 // 10x useful
14+
15+
class X:
16+
def extensionInCompanion: String = ???
17+
@nowarn // extensionInCompanion
18+
object X:
19+
implicit def companionConversion(x: X): B = ???
20+
21+
extension (x: X) def extensionInCompanion: String = ???

0 commit comments

Comments
 (0)