Skip to content

Commit 45e5c50

Browse files
committed
Add -W enabling warnings
1 parent 4554131 commit 45e5c50

File tree

4 files changed

+162
-6
lines changed

4 files changed

+162
-6
lines changed

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

+34-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package config
33

44
import scala.language.unsafeNulls
55
import dotty.tools.dotc.config.PathResolver.Defaults
6-
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingCategory}
6+
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingCategory, SettingsState}
77
import dotty.tools.dotc.config.SourceVersion
88
import dotty.tools.dotc.core.Contexts.*
99
import dotty.tools.dotc.rewrites.Rewrites
@@ -156,13 +156,42 @@ private sealed trait VerboseSettings:
156156
private sealed trait WarningSettings:
157157
self: SettingGroup =>
158158

159-
val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "W", "Print a synopsis of warning options.")
159+
val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "Whelp", "Print a synopsis of warning options.")
160+
161+
val W: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
162+
WarningSetting,
163+
name = "W",
164+
helpArg = "warning",
165+
descr = "Enable sets of warnings or print a synopsis of warning options.",
166+
choices = List(
167+
ChoiceWithHelp("default", "Enable default warnings"),
168+
ChoiceWithHelp("all", "Enable all warnings"),
169+
),
170+
default = Nil
171+
)
172+
173+
enum WarningGroup(val enabledBy: Set[String]):
174+
case Default extends WarningGroup(Set("default", "all"))
175+
case All extends WarningGroup(Set("all"))
176+
177+
def overrideValueWithW[T](group: WarningGroup, overrideWhen: T, overrideTo: T)(ss: SettingsState, v: T): T =
178+
if W.valueIn(ss).map(_.toString).exists(group.enabledBy.contains) && v == overrideWhen then overrideTo
179+
else v
180+
181+
def overrideWithW(group: WarningGroup)(ss: SettingsState, v: Boolean): Boolean =
182+
overrideValueWithW(group, false, true)(ss, v)
183+
160184
val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings"))
185+
.mapValue(overrideWithW(WarningGroup.Default))
161186
val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "Wvalue-discard", "Warn when non-Unit expression results are unused.")
187+
.mapValue(overrideWithW(WarningGroup.Default))
162188
val WNonUnitStatement = BooleanSetting(WarningSetting, "Wnonunit-statement", "Warn when block statements are non-Unit expressions.")
189+
.mapValue(overrideWithW(WarningGroup.Default))
163190
val WenumCommentDiscard = BooleanSetting(WarningSetting, "Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.")
164191
val WimplausiblePatterns = BooleanSetting(WarningSetting, "Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.")
192+
.mapValue(overrideWithW(WarningGroup.Default))
165193
val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.")
194+
.mapValue(overrideWithW(WarningGroup.Default))
166195
val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
167196
WarningSetting,
168197
name = "Wunused",
@@ -195,7 +224,8 @@ private sealed trait WarningSettings:
195224
)
196225
),
197226
default = Nil
198-
)
227+
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("linted", ""))))
228+
199229
object WunusedHas:
200230
def isChoiceSet(s: String)(using Context) = Wunused.value.pipe(us => us.contains(s))
201231
def allOr(s: String)(using Context) = Wunused.value.pipe(us => us.contains("all") || us.contains(s))
@@ -282,7 +312,7 @@ private sealed trait WarningSettings:
282312
ChoiceWithHelp("type-parameter-shadow", "Warn when a type parameter shadows a type already in the scope"),
283313
),
284314
default = Nil
285-
)
315+
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("all", ""))))
286316

287317
object WshadowHas:
288318
def allOr(s: String)(using Context) =

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ object Settings:
8282
propertyClass: Option[Class[?]] = None,
8383
deprecationMsg: Option[String] = None,
8484
// kept only for -Ykind-projector option compatibility
85-
legacyArgs: Boolean = false)(private[Settings] val idx: Int) {
85+
legacyArgs: Boolean = false,
86+
mapValue: (SettingsState, T) => T = (a, b: T) => b)(private[Settings] val idx: Int) {
87+
8688

8789
validateSettingString(prefix.getOrElse(name))
8890
aliases.foreach(validateSettingString)
@@ -94,7 +96,7 @@ object Settings:
9496

9597
val allFullNames: List[String] = s"$name" :: s"-$name" :: aliases
9698

97-
def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T]
99+
def valueIn(state: SettingsState): T = mapValue(state, state.value(idx).asInstanceOf[T])
98100

99101
def updateIn(state: SettingsState, x: Any): SettingsState = x match
100102
case _: T => state.update(idx, x)
@@ -114,6 +116,8 @@ object Settings:
114116
case None => ""
115117
}
116118

119+
def mapValue(f: (SettingsState, T) => T): Setting[T] = copy(mapValue = f)(idx)
120+
117121
def tryToSet(state: ArgsSummary): ArgsSummary = {
118122
val ArgsSummary(sstate, arg :: args, errors, warnings) = state: @unchecked
119123
def update(value: Any, args: List[String]): ArgsSummary =

tests/warn/i18559.check

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
-- [E176] Potential Issue Warning: tests/warn/i18559.scala:63:4 --------------------------------------------------------
2+
63 | improved // warn
3+
| ^^^^^^^^
4+
| unused value of type (improved : => scala.concurrent.Future[Int])
5+
-- [E175] Potential Issue Warning: tests/warn/i18559.scala:51:35 -------------------------------------------------------
6+
51 | firstThing().map(_ => secondThing()) // warn
7+
| ^^^^^^^^^^^^^
8+
| discarded non-Unit value of type Either[Failed, Unit]
9+
-- [E175] Potential Issue Warning: tests/warn/i18559.scala:54:35 -------------------------------------------------------
10+
54 | firstThing().map(_ => secondThing()) // warn
11+
| ^^^^^^^^^^^^^
12+
| discarded non-Unit value of type Either[Failed, Unit]
13+
-- Warning: tests/warn/i18559.scala:4:6 --------------------------------------------------------------------------------
14+
4 | var e3 = 2 // warn
15+
| ^^
16+
| unused local definition
17+
-- Warning: tests/warn/i18559.scala:8:28 -------------------------------------------------------------------------------
18+
8 | import collection.mutable.Set // warn
19+
| ^^^
20+
| unused import
21+
-- Warning: tests/warn/i18559.scala:9:33 -------------------------------------------------------------------------------
22+
9 | import collection.mutable.{Map => MutMap} // warn
23+
| ^^^^^^^^^^^^^
24+
| unused import
25+
-- Warning: tests/warn/i18559.scala:10:28 ------------------------------------------------------------------------------
26+
10 | import collection.mutable._ // warn
27+
| ^
28+
| unused import
29+
-- Warning: tests/warn/i18559.scala:13:28 ------------------------------------------------------------------------------
30+
13 | import collection.mutable._ // warn
31+
| ^
32+
| unused import
33+
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:31:10 ------------------------------------------------
34+
31 | case Sum(a@S(_),Z) => Z // warn
35+
| ^^^^^^^^^^^^^
36+
| Unreachable case
37+
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:32:10 ------------------------------------------------
38+
32 | case Sum(a@S(_),Z) => a // warn unreachable
39+
| ^^^^^^^^^^^^^
40+
| Unreachable case
41+
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:33:10 ------------------------------------------------
42+
33 | case Sum(a@S(b@S(_)), Z) => a // warn
43+
| ^^^^^^^^^^^^^^^^^^^
44+
| Unreachable case
45+
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:34:10 ------------------------------------------------
46+
34 | case Sum(a@S(b@S(_)), Z) => a // warn
47+
| ^^^^^^^^^^^^^^^^^^^
48+
| Unreachable case
49+
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:35:10 ------------------------------------------------
50+
35 | case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable
51+
| ^^^^^^^^^^^^^^^^^^^^^
52+
| Unreachable case
53+
-- [E121] Pattern Match Warning: tests/warn/i18559.scala:37:7 ----------------------------------------------------------
54+
37 | case _ => Z // warn unreachable
55+
| ^
56+
| Unreachable case except for null (if this is intentional, consider writing case null => instead).

tests/warn/i18559.scala

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//> using options -W:default
2+
3+
val b = // OK
4+
var e3 = 2 // warn
5+
1
6+
7+
object FooUnused:
8+
import collection.mutable.Set // warn
9+
import collection.mutable.{Map => MutMap} // warn
10+
import collection.mutable._ // warn
11+
12+
object FooWildcardUnused:
13+
import collection.mutable._ // warn
14+
15+
object Foo:
16+
import collection.mutable.Set // OK
17+
import collection.mutable.{Map => MutMap} // OK
18+
19+
val bar = Set() // OK
20+
val baz = MutMap() // OK
21+
22+
sealed trait Calc
23+
sealed trait Const extends Calc
24+
case class Sum(a: Calc, b: Calc) extends Calc
25+
case class S(pred: Const) extends Const
26+
case object Z extends Const
27+
28+
val a = Sum(S(S(Z)),Z) match {
29+
case Sum(a,Z) => Z // not warn: patvars not enabled by Wall
30+
// case Sum(a @ _,Z) => Z // todo : this should pass in the future
31+
case Sum(a@S(_),Z) => Z // warn
32+
case Sum(a@S(_),Z) => a // warn unreachable
33+
case Sum(a@S(b@S(_)), Z) => a // warn
34+
case Sum(a@S(b@S(_)), Z) => a // warn
35+
case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable
36+
case Sum(_,_) => Z // OK
37+
case _ => Z // warn unreachable
38+
}
39+
import scala.util.{Either, Right, Left}
40+
import scala.collection.mutable
41+
42+
case class Failed(msg: String)
43+
44+
def firstThing(): Either[Failed, Unit] =
45+
Right(())
46+
47+
def secondThing(): Either[Failed, Unit] =
48+
Left(Failed("whoops you should have flatMapped me"))
49+
50+
def singleExpr(): Either[Failed, Unit] =
51+
firstThing().map(_ => secondThing()) // warn
52+
53+
def block(): Either[Failed, Unit] = {
54+
firstThing().map(_ => secondThing()) // warn
55+
}
56+
57+
class C {
58+
import concurrent._
59+
import ExecutionContext.Implicits._
60+
def c = {
61+
def improved = Future(42)
62+
def stale = Future(27)
63+
improved // warn
64+
stale
65+
}
66+
}

0 commit comments

Comments
 (0)