Skip to content

Commit d1bf6ee

Browse files
Backport "Add the -Wall option that enables all warnings (Plan B)" to LTS (#22107)
Backports #20577 to the 3.3.5. PR submitted by the release tooling. [skip ci]
2 parents 56dbb7e + f372d14 commit d1bf6ee

File tree

14 files changed

+124
-35
lines changed

14 files changed

+124
-35
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+39-26
Original file line numberDiff line numberDiff line change
@@ -165,46 +165,50 @@ private sealed trait WarningSettings:
165165

166166
val Whelp: Setting[Boolean] = BooleanSetting("-W", "Print a synopsis of warning options.")
167167
val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings"))
168-
val WvalueDiscard: Setting[Boolean] = BooleanSetting("-Wvalue-discard", "Warn when non-Unit expression results are unused.")
169-
val WNonUnitStatement = BooleanSetting("-Wnonunit-statement", "Warn when block statements are non-Unit expressions.")
170-
val WenumCommentDiscard = BooleanSetting("-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.")
171-
val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
168+
val Wall: Setting[Boolean] = BooleanSetting("-Wall", "Enable all warning settings.")
169+
private val WvalueDiscard: Setting[Boolean] = BooleanSetting("-Wvalue-discard", "Warn when non-Unit expression results are unused.")
170+
private val WNonUnitStatement = BooleanSetting("-Wnonunit-statement", "Warn when block statements are non-Unit expressions.")
171+
private val WenumCommentDiscard = BooleanSetting("-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.")
172+
private val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
172173
name = "-Wunused",
173174
helpArg = "warning",
174175
descr = "Enable or disable specific `unused` warnings",
175-
choices = List(
176+
choices = List(
176177
ChoiceWithHelp("nowarn", ""),
177-
ChoiceWithHelp("all",""),
178+
ChoiceWithHelp("all", ""),
178179
ChoiceWithHelp(
179180
name = "imports",
180181
description = "Warn if an import selector is not referenced.\n" +
181182
"NOTE : overrided by -Wunused:strict-no-implicit-warn"),
182-
ChoiceWithHelp("privates","Warn if a private member is unused"),
183-
ChoiceWithHelp("locals","Warn if a local definition is unused"),
184-
ChoiceWithHelp("explicits","Warn if an explicit parameter is unused"),
185-
ChoiceWithHelp("implicits","Warn if an implicit parameter is unused"),
186-
ChoiceWithHelp("params","Enable -Wunused:explicits,implicits"),
187-
ChoiceWithHelp("linted","Enable -Wunused:imports,privates,locals,implicits"),
188-
ChoiceWithHelp(
189-
name = "strict-no-implicit-warn",
190-
description = "Same as -Wunused:import, only for imports of explicit named members.\n" +
191-
"NOTE : This overrides -Wunused:imports and NOT set by -Wunused:all"
192-
),
193-
// ChoiceWithHelp("patvars","Warn if a variable bound in a pattern is unused"),
194-
ChoiceWithHelp(
195-
name = "unsafe-warn-patvars",
196-
description = "(UNSAFE) Warn if a variable bound in a pattern is unused.\n" +
197-
"This warning can generate false positive, as warning cannot be\n" +
198-
"suppressed yet."
199-
)
183+
ChoiceWithHelp("privates", "Warn if a private member is unused"),
184+
ChoiceWithHelp("locals", "Warn if a local definition is unused"),
185+
ChoiceWithHelp("explicits", "Warn if an explicit parameter is unused"),
186+
ChoiceWithHelp("implicits", "Warn if an implicit parameter is unused"),
187+
ChoiceWithHelp("params", "Enable -Wunused:explicits,implicits"),
188+
ChoiceWithHelp("linted", "Enable -Wunused:imports,privates,locals,implicits"),
189+
ChoiceWithHelp(
190+
name = "strict-no-implicit-warn",
191+
description = "Same as -Wunused:import, only for imports of explicit named members.\n" +
192+
"NOTE : This overrides -Wunused:imports and NOT set by -Wunused:all"
193+
),
194+
// ChoiceWithHelp("patvars","Warn if a variable bound in a pattern is unused"),
195+
ChoiceWithHelp(
196+
name = "unsafe-warn-patvars",
197+
description = "(UNSAFE) Warn if a variable bound in a pattern is unused.\n" +
198+
"This warning can generate false positive, as warning cannot be\n" +
199+
"suppressed yet."
200+
)
200201
),
201202
default = Nil
202203
)
203204
object WunusedHas:
204205
def isChoiceSet(s: String)(using Context) = Wunused.value.pipe(us => us.contains(s))
205-
def allOr(s: String)(using Context) = Wunused.value.pipe(us => us.contains("all") || us.contains(s))
206+
def allOr(s: String)(using Context) = Wall.value || Wunused.value.pipe(us => us.contains("all") || us.contains(s))
206207
def nowarn(using Context) = allOr("nowarn")
207208

209+
// Is any choice set for -Wunused?
210+
def any(using Context): Boolean = Wall.value || Wunused.value.nonEmpty
211+
208212
// overrided by strict-no-implicit-warn
209213
def imports(using Context) =
210214
(allOr("imports") || allOr("linted")) && !(strictNoImplicitWarn)
@@ -278,6 +282,16 @@ private sealed trait WarningSettings:
278282
|to prevent the shell from expanding patterns.""".stripMargin,
279283
)
280284

285+
val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects.")
286+
287+
object Whas:
288+
def allOr(s: Setting[Boolean])(using Context): Boolean =
289+
Wall.value || s.value
290+
def valueDiscard(using Context): Boolean = allOr(WvalueDiscard)
291+
def nonUnitStatement(using Context): Boolean = allOr(WNonUnitStatement)
292+
def enumCommentDiscard(using Context): Boolean = allOr(WenumCommentDiscard)
293+
def checkInit(using Context): Boolean = allOr(YcheckInit)
294+
281295
/** -X "Extended" or "Advanced" settings */
282296
private sealed trait XSettings:
283297
self: SettingGroup =>
@@ -415,7 +429,6 @@ private sealed trait YSettings:
415429
// Experimental language features
416430
val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting("-Yno-kind-polymorphism", "Disable kind polymorphism.")
417431
val YexplicitNulls: Setting[Boolean] = BooleanSetting("-Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.")
418-
val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects.")
419432
val YrequireTargetName: Setting[Boolean] = BooleanSetting("-Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation.")
420433
val YrecheckTest: Setting[Boolean] = BooleanSetting("-Yrecheck-test", "Run basic rechecking (internal test only).")
421434
val YccDebug: Setting[Boolean] = BooleanSetting("-Ycc-debug", "Used in conjunction with captureChecking language import, debug info for captured references.")

compiler/src/dotty/tools/dotc/core/Symbols.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ object Symbols extends SymUtils {
8080
ctx.settings.YretainTrees.value ||
8181
denot.owner.isTerm || // no risk of leaking memory after a run for these
8282
denot.isOneOf(InlineOrProxy) || // need to keep inline info
83-
ctx.settings.YcheckInit.value // initialization check
83+
ctx.settings.Whas.checkInit // initialization check
8484

8585
/** The last denotation of this symbol */
8686
private var lastDenot: SymDenotation = _

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3923,7 +3923,7 @@ object Parsers {
39233923
if (in.token == COMMA) {
39243924
in.nextToken()
39253925
val ids = commaSeparated(() => termIdent())
3926-
if ctx.settings.WenumCommentDiscard.value then
3926+
if ctx.settings.Whas.enumCommentDiscard then
39273927
in.getDocComment(start).foreach: comm =>
39283928
warning(
39293929
em"""Ambiguous Scaladoc comment on multiple cases is ignored.

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
5858

5959
override def isRunnable(using Context): Boolean =
6060
super.isRunnable &&
61-
ctx.settings.Wunused.value.nonEmpty &&
61+
ctx.settings.WunusedHas.any &&
6262
!ctx.isJava
6363

6464
// ========== SETUP ============

compiler/src/dotty/tools/dotc/transform/init/Checker.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Checker extends Phase:
2929
override val runsAfter = Set(Pickler.name)
3030

3131
override def isEnabled(using Context): Boolean =
32-
super.isEnabled && ctx.settings.YcheckInit.value
32+
super.isEnabled && ctx.settings.Whas.checkInit
3333

3434
def traverse(traverser: InitTreeTraverser)(using Context): Boolean = monitor(phaseName):
3535
val unit = ctx.compilationUnit
@@ -46,7 +46,8 @@ class Checker extends Phase:
4646
cancellable {
4747
val classes = traverser.getClasses()
4848

49-
Semantic.checkClasses(classes)(using checkCtx)
49+
if ctx.settings.Whas.checkInit then
50+
Semantic.checkClasses(classes)(using checkCtx)
5051
}
5152

5253
units0

compiler/src/dotty/tools/dotc/typer/Typer.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -4196,7 +4196,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
41964196
// so will take the code path that decides on inlining
41974197
val tree1 = adapt(tree, WildcardType, locked)
41984198
checkStatementPurity(tree1)(tree, ctx.owner, isUnitExpr = true)
4199-
if (!ctx.isAfterTyper && !tree.isInstanceOf[Inlined] && ctx.settings.WvalueDiscard.value && !isThisTypeResult(tree)) {
4199+
if (!ctx.isAfterTyper && !tree.isInstanceOf[Inlined] && ctx.settings.Whas.valueDiscard && !isThisTypeResult(tree)) {
42004200
report.warning(ValueDiscarding(tree.tpe), tree.srcPos)
42014201
}
42024202
return tpd.Block(tree1 :: Nil, unitLiteral)
@@ -4498,7 +4498,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
44984498
&& !isJavaApplication(t) // Java methods are inherently side-effecting
44994499
// && !treeInfo.hasExplicitUnit(t) // suppressed by explicit expr: Unit // TODO Should explicit `: Unit` be added as warning suppression?
45004500
)
4501-
if ctx.settings.WNonUnitStatement.value && !ctx.isAfterTyper && checkInterestingShapes(t) then
4501+
if ctx.settings.Whas.nonUnitStatement && !ctx.isAfterTyper && checkInterestingShapes(t) then
45024502
val where = t match {
45034503
case Block(_, res) => res
45044504
case If(_, thenpart, Literal(Constant(()))) =>

tests/pos-with-compiler-cc/dotc/core/Symbols.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ object Symbols {
8383
ctx.settings.YretainTrees.value ||
8484
denot.owner.isTerm || // no risk of leaking memory after a run for these
8585
denot.isOneOf(InlineOrProxy) || // need to keep inline info
86-
ctx.settings.YcheckInit.value // initialization check
86+
ctx.settings.Whas.checkInit // initialization check
8787

8888
/** The last denotation of this symbol */
8989
private var lastDenot: SymDenotation = _

tests/pos-with-compiler-cc/dotc/transform/init/Checker.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Checker extends Phase:
2828
override val runsAfter = Set(Pickler.name)
2929

3030
override def isEnabled(using Context): Boolean =
31-
super.isEnabled && ctx.settings.YcheckInit.value
31+
super.isEnabled && ctx.settings.Whas.checkInit
3232

3333
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
3434
val checkCtx = ctx.fresh.setPhase(this.start)

tests/warn/i18559a.check

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- [E198] Unused Symbol Warning: tests/warn/i18559a.scala:4:28 ---------------------------------------------------------
2+
4 | import collection.mutable.Set // warn
3+
| ^^^
4+
| unused import
5+
-- [E198] Unused Symbol Warning: tests/warn/i18559a.scala:8:8 ----------------------------------------------------------
6+
8 | val x = 1 // warn
7+
| ^
8+
| unused local definition
9+
-- [E198] Unused Symbol Warning: tests/warn/i18559a.scala:11:26 --------------------------------------------------------
10+
11 | import SomeGivenImports.given // warn
11+
| ^^^^^
12+
| unused import

tests/warn/i18559a.scala

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//> using options -Wall
2+
// This test checks that -Wall turns on -Wunused:all if -Wunused is not set
3+
object FooImportUnused:
4+
import collection.mutable.Set // warn
5+
6+
object FooUnusedLocal:
7+
def test(): Unit =
8+
val x = 1 // warn
9+
10+
object FooGivenUnused:
11+
import SomeGivenImports.given // warn
12+
13+
object SomeGivenImports:
14+
given Int = 0
15+
given String = "foo"

tests/warn/i18559b.check

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- Warning: tests/warn/i18559b.scala:8:6 -------------------------------------------------------------------------------
2+
8 | val localFile: String = s"${url.##}.tmp" // warn
3+
| ^
4+
| Access non-initialized value localFile. Calling trace:
5+
| -> class RemoteFile(url: String) extends AbstractFile: [ i18559b.scala:7 ]
6+
| ^
7+
| -> abstract class AbstractFile: [ i18559b.scala:3 ]
8+
| ^
9+
| -> val extension: String = name.substring(4) [ i18559b.scala:5 ]
10+
| ^^^^
11+
| -> def name: String = localFile [ i18559b.scala:9 ]
12+
| ^^^^^^^^^

tests/warn/i18559b.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//> using options -Wall
2+
// This test checks that -Wall turns on -Wsafe-init
3+
abstract class AbstractFile:
4+
def name: String
5+
val extension: String = name.substring(4)
6+
7+
class RemoteFile(url: String) extends AbstractFile:
8+
val localFile: String = s"${url.##}.tmp" // warn
9+
def name: String = localFile

tests/warn/i18559c.check

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- [E198] Unused Symbol Warning: tests/warn/i18559c.scala:4:28 ---------------------------------------------------------
2+
4 | import collection.mutable.Set // warn
3+
| ^^^
4+
| unused import
5+
-- [E198] Unused Symbol Warning: tests/warn/i18559c.scala:8:8 ----------------------------------------------------------
6+
8 | val x = 1 // warn
7+
| ^
8+
| unused local definition
9+
-- [E198] Unused Symbol Warning: tests/warn/i18559c.scala:11:26 --------------------------------------------------------
10+
11 | import SomeGivenImports.given // warn
11+
| ^^^^^
12+
| unused import

tests/warn/i18559c.scala

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//> using options -Wall -Wunused:locals
2+
// This test checks that -Wall overrides -Wunused:... if it is already set
3+
object FooImportUnused:
4+
import collection.mutable.Set // warn
5+
6+
object FooUnusedLocal:
7+
def test(): Unit =
8+
val x = 1 // warn
9+
10+
object FooGivenUnused:
11+
import SomeGivenImports.given // warn
12+
13+
object SomeGivenImports:
14+
given Int = 0
15+
given String = "foo"

0 commit comments

Comments
 (0)