Skip to content

Commit

Permalink
Add -W enabling warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
szymon-rd committed Mar 19, 2024
1 parent 4554131 commit 45e5c50
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 6 deletions.
38 changes: 34 additions & 4 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package config

import scala.language.unsafeNulls
import dotty.tools.dotc.config.PathResolver.Defaults
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingCategory}
import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingCategory, SettingsState}
import dotty.tools.dotc.config.SourceVersion
import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.rewrites.Rewrites
Expand Down Expand Up @@ -156,13 +156,42 @@ private sealed trait VerboseSettings:
private sealed trait WarningSettings:
self: SettingGroup =>

val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "W", "Print a synopsis of warning options.")
val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "Whelp", "Print a synopsis of warning options.")

val W: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
WarningSetting,
name = "W",
helpArg = "warning",
descr = "Enable sets of warnings or print a synopsis of warning options.",
choices = List(
ChoiceWithHelp("default", "Enable default warnings"),
ChoiceWithHelp("all", "Enable all warnings"),
),
default = Nil
)

enum WarningGroup(val enabledBy: Set[String]):
case Default extends WarningGroup(Set("default", "all"))
case All extends WarningGroup(Set("all"))

def overrideValueWithW[T](group: WarningGroup, overrideWhen: T, overrideTo: T)(ss: SettingsState, v: T): T =
if W.valueIn(ss).map(_.toString).exists(group.enabledBy.contains) && v == overrideWhen then overrideTo
else v

def overrideWithW(group: WarningGroup)(ss: SettingsState, v: Boolean): Boolean =
overrideValueWithW(group, false, true)(ss, v)

val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings"))
.mapValue(overrideWithW(WarningGroup.Default))
val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "Wvalue-discard", "Warn when non-Unit expression results are unused.")
.mapValue(overrideWithW(WarningGroup.Default))
val WNonUnitStatement = BooleanSetting(WarningSetting, "Wnonunit-statement", "Warn when block statements are non-Unit expressions.")
.mapValue(overrideWithW(WarningGroup.Default))
val WenumCommentDiscard = BooleanSetting(WarningSetting, "Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.")
val WimplausiblePatterns = BooleanSetting(WarningSetting, "Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.")
.mapValue(overrideWithW(WarningGroup.Default))
val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.")
.mapValue(overrideWithW(WarningGroup.Default))
val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
WarningSetting,
name = "Wunused",
Expand Down Expand Up @@ -195,7 +224,8 @@ private sealed trait WarningSettings:
)
),
default = Nil
)
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("linted", ""))))

object WunusedHas:
def isChoiceSet(s: String)(using Context) = Wunused.value.pipe(us => us.contains(s))
def allOr(s: String)(using Context) = Wunused.value.pipe(us => us.contains("all") || us.contains(s))
Expand Down Expand Up @@ -282,7 +312,7 @@ private sealed trait WarningSettings:
ChoiceWithHelp("type-parameter-shadow", "Warn when a type parameter shadows a type already in the scope"),
),
default = Nil
)
).mapValue(overrideValueWithW(WarningGroup.Default, Nil, List(ChoiceWithHelp("all", ""))))

object WshadowHas:
def allOr(s: String)(using Context) =
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/config/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ object Settings:
propertyClass: Option[Class[?]] = None,
deprecationMsg: Option[String] = None,
// kept only for -Ykind-projector option compatibility
legacyArgs: Boolean = false)(private[Settings] val idx: Int) {
legacyArgs: Boolean = false,
mapValue: (SettingsState, T) => T = (a, b: T) => b)(private[Settings] val idx: Int) {


validateSettingString(prefix.getOrElse(name))
aliases.foreach(validateSettingString)
Expand All @@ -94,7 +96,7 @@ object Settings:

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

def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T]
def valueIn(state: SettingsState): T = mapValue(state, state.value(idx).asInstanceOf[T])

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

def mapValue(f: (SettingsState, T) => T): Setting[T] = copy(mapValue = f)(idx)

def tryToSet(state: ArgsSummary): ArgsSummary = {
val ArgsSummary(sstate, arg :: args, errors, warnings) = state: @unchecked
def update(value: Any, args: List[String]): ArgsSummary =
Expand Down
56 changes: 56 additions & 0 deletions tests/warn/i18559.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- [E176] Potential Issue Warning: tests/warn/i18559.scala:63:4 --------------------------------------------------------
63 | improved // warn
| ^^^^^^^^
| unused value of type (improved : => scala.concurrent.Future[Int])
-- [E175] Potential Issue Warning: tests/warn/i18559.scala:51:35 -------------------------------------------------------
51 | firstThing().map(_ => secondThing()) // warn
| ^^^^^^^^^^^^^
| discarded non-Unit value of type Either[Failed, Unit]
-- [E175] Potential Issue Warning: tests/warn/i18559.scala:54:35 -------------------------------------------------------
54 | firstThing().map(_ => secondThing()) // warn
| ^^^^^^^^^^^^^
| discarded non-Unit value of type Either[Failed, Unit]
-- Warning: tests/warn/i18559.scala:4:6 --------------------------------------------------------------------------------
4 | var e3 = 2 // warn
| ^^
| unused local definition
-- Warning: tests/warn/i18559.scala:8:28 -------------------------------------------------------------------------------
8 | import collection.mutable.Set // warn
| ^^^
| unused import
-- Warning: tests/warn/i18559.scala:9:33 -------------------------------------------------------------------------------
9 | import collection.mutable.{Map => MutMap} // warn
| ^^^^^^^^^^^^^
| unused import
-- Warning: tests/warn/i18559.scala:10:28 ------------------------------------------------------------------------------
10 | import collection.mutable._ // warn
| ^
| unused import
-- Warning: tests/warn/i18559.scala:13:28 ------------------------------------------------------------------------------
13 | import collection.mutable._ // warn
| ^
| unused import
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:31:10 ------------------------------------------------
31 | case Sum(a@S(_),Z) => Z // warn
| ^^^^^^^^^^^^^
| Unreachable case
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:32:10 ------------------------------------------------
32 | case Sum(a@S(_),Z) => a // warn unreachable
| ^^^^^^^^^^^^^
| Unreachable case
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:33:10 ------------------------------------------------
33 | case Sum(a@S(b@S(_)), Z) => a // warn
| ^^^^^^^^^^^^^^^^^^^
| Unreachable case
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:34:10 ------------------------------------------------
34 | case Sum(a@S(b@S(_)), Z) => a // warn
| ^^^^^^^^^^^^^^^^^^^
| Unreachable case
-- [E030] Match case Unreachable Warning: tests/warn/i18559.scala:35:10 ------------------------------------------------
35 | case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable
| ^^^^^^^^^^^^^^^^^^^^^
| Unreachable case
-- [E121] Pattern Match Warning: tests/warn/i18559.scala:37:7 ----------------------------------------------------------
37 | case _ => Z // warn unreachable
| ^
| Unreachable case except for null (if this is intentional, consider writing case null => instead).
66 changes: 66 additions & 0 deletions tests/warn/i18559.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//> using options -W:default

val b = // OK
var e3 = 2 // warn
1

object FooUnused:
import collection.mutable.Set // warn
import collection.mutable.{Map => MutMap} // warn
import collection.mutable._ // warn

object FooWildcardUnused:
import collection.mutable._ // warn

object Foo:
import collection.mutable.Set // OK
import collection.mutable.{Map => MutMap} // OK

val bar = Set() // OK
val baz = MutMap() // OK

sealed trait Calc
sealed trait Const extends Calc
case class Sum(a: Calc, b: Calc) extends Calc
case class S(pred: Const) extends Const
case object Z extends Const

val a = Sum(S(S(Z)),Z) match {
case Sum(a,Z) => Z // not warn: patvars not enabled by Wall
// case Sum(a @ _,Z) => Z // todo : this should pass in the future
case Sum(a@S(_),Z) => Z // warn
case Sum(a@S(_),Z) => a // warn unreachable
case Sum(a@S(b@S(_)), Z) => a // warn
case Sum(a@S(b@S(_)), Z) => a // warn
case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable
case Sum(_,_) => Z // OK
case _ => Z // warn unreachable
}
import scala.util.{Either, Right, Left}
import scala.collection.mutable

case class Failed(msg: String)

def firstThing(): Either[Failed, Unit] =
Right(())

def secondThing(): Either[Failed, Unit] =
Left(Failed("whoops you should have flatMapped me"))

def singleExpr(): Either[Failed, Unit] =
firstThing().map(_ => secondThing()) // warn

def block(): Either[Failed, Unit] = {
firstThing().map(_ => secondThing()) // warn
}

class C {
import concurrent._
import ExecutionContext.Implicits._
def c = {
def improved = Future(42)
def stale = Future(27)
improved // warn
stale
}
}

0 comments on commit 45e5c50

Please sign in to comment.