Skip to content

Commit

Permalink
SI-8736 Restore -language to former glory
Browse files Browse the repository at this point in the history
MultiChoice allows -language to work like -Xlint.

The bug as described was that the setting value was set instead of updated
(++=) with additional flags.

The unreported bug was that `_` no longer set all settings.

The corrected behavior is that "contains" means "it was enabled, or
_ was set and it was not disabled explicitly."

That is the behavior of `-Xlint` but with a different mechanism,
since each lint option is a Setting.

A semantic difference is that -Xlint enables all the lint options,
but -language does not enable all the language features. `scalac -X` does
not explain this additional behavior of the `-Xlint` flag.

Also worth noting that `scalac -feature -language unused.scala` failed
in 2.11.1 but succeeds silently now.
  • Loading branch information
som-snytt committed Jul 20, 2014
1 parent abdd570 commit 01da58e
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ trait AbsScalaSettings {
def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): ChoiceSetting
def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]): IntSetting
def MultiStringSetting(name: String, helpArg: String, descr: String): MultiStringSetting
def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: () => Unit)(helper: MultiChoiceSetting => String): MultiChoiceSetting
def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: Option[() => Unit])(helper: MultiChoiceSetting => String): MultiChoiceSetting
def OutputSetting(outputDirs: OutputDirs, default: String): OutputSetting
def PathSetting(name: String, descr: String, default: String): PathSetting
def PhasesSetting(name: String, descr: String, default: String): PhasesSetting
Expand Down
19 changes: 13 additions & 6 deletions src/compiler/scala/tools/nsc/settings/MutableSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class MutableSettings(val errorFn: String => Unit)
add(new ChoiceSetting(name, helpArg, descr, choices, default))
def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]) = add(new IntSetting(name, descr, default, range, parser))
def MultiStringSetting(name: String, arg: String, descr: String) = add(new MultiStringSetting(name, arg, descr))
def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: () => Unit = () => ())(
def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: Option[() => Unit] = None)(
helper: MultiChoiceSetting => String = _ => choices.mkString(f"$descr:%n", f"%n ", f"%n")
) =
add(new MultiChoiceSetting(name, helpArg, descr, choices, default, helper))
Expand Down Expand Up @@ -563,19 +563,21 @@ class MutableSettings(val errorFn: String => Unit)
arg: String,
descr: String,
override val choices: List[String],
val default: () => Unit,
val default: Option[() => Unit],
helper: MultiChoiceSetting => String
) extends MultiStringSetting(name, s"_,$arg,-$arg", s"$descr: `_' for all, `$name:help' to list") {

private def badChoice(s: String, n: String) = errorFn(s"'$s' is not a valid choice for '$name'")
private def choosing = choices.nonEmpty
private def isChoice(s: String) = (s == "_") || (choices contains (s stripPrefix "-"))

private var sawHelp = false
private var sawAll = false

override protected def tts(args: List[String], halting: Boolean) = {
val added = collection.mutable.ListBuffer.empty[String]
def tryArg(arg: String) = arg match {
case "_" if choosing => default()
case "_" if choosing => addAll()
case "help" if choosing => sawHelp = true
case s if !choosing || isChoice(s) => added += s
case s => badChoice(s, name)
Expand All @@ -587,13 +589,18 @@ class MutableSettings(val errorFn: String => Unit)
case Nil => Nil
}
val rest = loop(args)
if (rest.size == args.size) default() // if no arg consumed, trigger default action
else value = added.toList // update all new settings at once
if (rest.size == args.size) default foreach (_()) // if no arg consumed, trigger default action
else value ++= added.toList // update all new settings at once
Some(rest)
}

def isHelping: Boolean = sawHelp
def help: String = helper(this)
def help: String = helper(this)
private val adderAll = Some(() => sawAll = true)
def addAll(): Unit = default orElse adderAll foreach (_())

// the semantics is: s is enabled, i.e., either s or (_ but not -s)
override def contains(s: String) = isChoice(s) && (value contains s) || (sawAll && !(value contains s"-$s"))
}

/** A setting that accumulates all strings supplied to it,
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/settings/Warnings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ trait Warnings {
helpArg = "warning",
descr = description,
choices = choices,
default = () => xlint.value = true
default = Some(() => xlint.value = true)
) { s =>
def helpline(n: String) = lintWarnings.find(_.name == n).map(w => f" ${w.name}%-25s ${w.helpDescription}%n")
choices flatMap (helpline(_)) mkString (f"$description:%n", "", f"%n")
Expand Down
11 changes: 11 additions & 0 deletions test/files/neg/t8736-c.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
t8736-c.scala:4: warning: higher-kinded type should be enabled
by making the implicit value scala.language.higherKinds visible.
This can be achieved by adding the import clause 'import scala.language.higherKinds'
or by setting the compiler option -language:higherKinds.
See the Scala docs for value scala.language.higherKinds for a discussion
why the feature should be explicitly enabled.
def hk[M[_]] = ???
^
error: No warnings can be incurred under -Xfatal-warnings.
one warning found
one error found
1 change: 1 addition & 0 deletions test/files/neg/t8736-c.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-feature -language:-higherKinds,_ -Xfatal-warnings
7 changes: 7 additions & 0 deletions test/files/neg/t8736-c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// scalac: -feature -language:-higherKinds,_ -Xfatal-warnings
// showing that wildcard doesn't supersede explicit disablement
class X {
def hk[M[_]] = ???

implicit def imp(x: X): Int = x.hashCode
}
1 change: 1 addition & 0 deletions test/files/pos/t8736-b.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-feature -language:_ -Xfatal-warnings
7 changes: 7 additions & 0 deletions test/files/pos/t8736-b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// scalac: -feature -language:_ -Xfatal-warnings
// showing that all are set
class X {
def hk[M[_]] = ???

implicit def imp(x: X): Int = x.hashCode
}
1 change: 1 addition & 0 deletions test/files/pos/t8736.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-feature -language:implicitConversions -language:higherKinds -language:-implicitConversions -Xfatal-warnings
7 changes: 7 additions & 0 deletions test/files/pos/t8736.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// scalac: -feature -language:implicitConversions -language:higherKinds -language:-implicitConversions -Xfatal-warnings
// showing that multiple settings are respected, and explicit enablement has precedence
class X {
def hk[M[_]] = ???

implicit def imp(x: X): Int = x.hashCode
}

0 comments on commit 01da58e

Please sign in to comment.