Skip to content

Commit 3b400b5

Browse files
committed
Add -W enabling warnings
1 parent 25fc269 commit 3b400b5

File tree

4 files changed

+161
-6
lines changed

4 files changed

+161
-6
lines changed

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

+34-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package config
44
import scala.language.unsafeNulls
55
import dotty.tools.backend.jvm.BackendUtils.classfileVersionMap
66
import dotty.tools.dotc.config.PathResolver.Defaults
7-
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup}
7+
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingsState}
88
import dotty.tools.dotc.config.SourceVersion
99
import dotty.tools.dotc.core.Contexts.*
1010
import dotty.tools.dotc.rewrites.Rewrites
@@ -181,12 +181,41 @@ private sealed trait VerboseSettings:
181181
private sealed trait WarningSettings:
182182
self: SettingGroup =>
183183

184-
val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "W", "Print a synopsis of warning options.")
184+
val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "Whelp", "Print a synopsis of warning options.")
185+
186+
val W: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
187+
WarningSetting,
188+
name = "W",
189+
helpArg = "warning",
190+
descr = "Enable sets of warnings or print a synopsis of warning options.",
191+
choices = List(
192+
ChoiceWithHelp("default", "Enable default warnings"),
193+
ChoiceWithHelp("all", "Enable all warnings"),
194+
),
195+
default = Nil
196+
)
197+
198+
enum WarningGroup(val enabledBy: Set[String]):
199+
case Default extends WarningGroup(Set("default", "all"))
200+
case All extends WarningGroup(Set("all"))
201+
202+
def overrideValueWithW[T](group: WarningGroup, overrideWhen: T, overrideTo: T)(ss: SettingsState, v: T): T =
203+
if W.valueIn(ss).map(_.toString).exists(group.enabledBy.contains) && v == overrideWhen then overrideTo
204+
else v
205+
206+
def overrideWithW(group: WarningGroup)(ss: SettingsState, v: Boolean): Boolean =
207+
overrideValueWithW(group, false, true)(ss, v)
208+
185209
val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings"))
210+
.mapValue(overrideWithW(WarningGroup.Default))
186211
val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "Wvalue-discard", "Warn when non-Unit expression results are unused.")
212+
.mapValue(overrideWithW(WarningGroup.Default))
187213
val WNonUnitStatement = BooleanSetting(WarningSetting, "Wnonunit-statement", "Warn when block statements are non-Unit expressions.")
214+
.mapValue(overrideWithW(WarningGroup.Default))
188215
val WimplausiblePatterns = BooleanSetting(WarningSetting, "Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.")
216+
.mapValue(overrideWithW(WarningGroup.Default))
189217
val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.")
218+
.mapValue(overrideWithW(WarningGroup.Default))
190219
val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
191220
WarningSetting,
192221
name = "Wunused",
@@ -219,7 +248,8 @@ private sealed trait WarningSettings:
219248
)
220249
),
221250
default = Nil
222-
)
251+
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("linted", ""))))
252+
223253
object WunusedHas:
224254
def isChoiceSet(s: String)(using Context) = Wunused.value.pipe(us => us.contains(s))
225255
def allOr(s: String)(using Context) = Wunused.value.pipe(us => us.contains("all") || us.contains(s))
@@ -306,7 +336,7 @@ private sealed trait WarningSettings:
306336
ChoiceWithHelp("type-parameter-shadow", "Warn when a type parameter shadows a type already in the scope"),
307337
),
308338
default = Nil
309-
)
339+
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("all", ""))))
310340

311341
object XlintHas:
312342
def allOr(s: String)(using Context) =

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ object Settings:
7070
aliases: List[String] = Nil,
7171
depends: List[(Setting[?], Any)] = Nil,
7272
ignoreInvalidArgs: Boolean = false,
73-
propertyClass: Option[Class[?]] = None)(private[Settings] val idx: Int) {
73+
propertyClass: Option[Class[?]] = None,
74+
mapValue: (SettingsState, T) => T = (a, b: T) => b)(private[Settings] val idx: Int) {
7475

7576
assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category")
7677

7778
val allFullNames: List[String] = s"$name" :: s"-$name" :: aliases
7879

79-
def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T]
80+
def valueIn(state: SettingsState): T = mapValue(state, state.value(idx).asInstanceOf[T])
8081

8182
def updateIn(state: SettingsState, x: Any): SettingsState = x match
8283
case _: T => state.update(idx, x)
@@ -96,6 +97,8 @@ object Settings:
9697
case None => ""
9798
}
9899

100+
def mapValue(f: (SettingsState, T) => T): Setting[T] = copy(mapValue = f)(idx)
101+
99102
def tryToSet(state: ArgsSummary): ArgsSummary = {
100103
val ArgsSummary(sstate, arg :: args, errors, warnings) = state: @unchecked
101104
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)