-Wunused on Scala 3.3.0+

So I’m running into a bit of a weird one.

$ cs launch scala:3.3.0 -- -W
      -Wunused  Enable or disable specific `unused` warnings
                 Choices : 
                 - nowarn, 
                 - all, 
                 - imports :
                        Warn if an import selector is not referenced.
                        NOTE : overrided by -Wunused:strict-no-implicit-warn, 

(note that it mentions disabling, but not exactly how)

so I tried the 2.13 cmdline syntax (by prefixing with a dash), but that doesn’t seem to work:

$ cs launch scala:3.3.0 -- -Wunused:all,-implicits
invalid choice(s) for -Wunused: -implicits
  scala -help  gives more information

… so, how exactly does one disable individual options? (I’m using this for a build where I’d like to always be opted in to the latest warnings whenever we change to a newer version of the compiler.)

EDIT: I should add: Using separate options as in -Wunused:all -Wunused:-implicits doesn’t work either.

It works for me with scala-cli:

$ scala-cli repl -S 3.3 -Wunused:all
Welcome to Scala 3.3.0 (17.0.6, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> def f = {val x = 42; 43}
1 warning found
-- Warning: --------------------------------------------------------------------
1 |def f = {val x = 42; 43}
  |             ^
  |             unused local definition
def f: Int

-Wunused:all works fine for me as well, it’s the “turn off selectively” bit that I’m asking about.

I guess you can explicitly enumerate the ones you do want, one by one (and exclude the ones you don’t want). Something like:

$ scala-cli repl -S 3.3 -Wunused:imports,privates,locals
Welcome to Scala 3.3.0 (17.0.6, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> class A{ private val x = 42}
1 warning found
-- Warning: --------------------------------------------------------------------
1 |class A{ private val x = 42}
  |                     ^
  |                     unused private member
// defined class A

See details by the -W synopsis print:

$ scala-cli compile -S 3.3 -W
Usage: scalac <options> <source files>

    |-- Notes on option parsing --
    |Boolean settings are always false unless set.
    |Where multiple values are accepted, they should be comma-separated.
    |  example: -Xplugin:plugin1,plugin2
    |<phases> means one or a comma-separated list of:
    |  - (partial) phase names with an optional "+" suffix to include the next phase
    |  - the string "all"
    |  example: -Xprint:all prints all phases.
    |  example: -Xprint:typer,mixin prints the typer and mixin phases.
    |  example: -Ylog:erasure+ logs the erasure phase and the phase after the erasure phase.
    |           This is useful because during the tree transform of phase X, we often
    |           already are in phase X + 1.
Possible warning options include:
         -Wconf  Configure compiler warnings.
        -Werror  Fail the compilation if there are any warnings.
       -Wunused  Enable or disable specific `unused` warnings
                 Choices : 
                 - nowarn, 
                 - all, 
                 - imports :
                 	Warn if an import selector is not referenced.
                 	NOTE : overrided by -Wunused:strict-no-implicit-warn, 
                 - privates :
                 	Warn if a private member is unused, 
                 - locals :
                 	Warn if a local definition is unused, 
                 - explicits :
                 	Warn if an explicit parameter is unused, 
                 - implicits :
                 	Warn if an implicit parameter is unused, 
                 - params :
                 	Enable -Wunused:explicits,implicits, 
                 - linted :
                 	Enable -Wunused:imports,privates,locals,implicits, 
                 - strict-no-implicit-warn :
                 	Same as -Wunused:import, only for imports of explicit named
                 	NOTE : This overrides -Wunused:imports and NOT set by
                 - unsafe-warn-patvars :
                 	(UNSAFE) Warn if a variable bound in a pattern is unused.
                 	This warning can generate false positive, as warning cannot be
                 	suppressed yet.
-Wvalue-discard  Warn when non-Unit expression results are unused.
        @<file>  A text file containing compiler arguments (options and source

I know. See the parenthetical remark in the original post about why I want “all” and to turn off individual ones I don’t want.

“disable” syntax evolved on Scala 2, so it’s likely that Scala 3 is still catching up. Probably we should invent a better term. “quiesce” might be too Latinate, but maybe it would be fine. “Quiescent syntax.”

I think forward-porting such behaviors is also an opportunity to take stock and decide how it should work in future.

IIRC on Scala 2, turning off an option is always respected. That is non-trivial, in that an option may be set redundantly in a build.

The other idiom is -deprecated:false. I don’t know if that is supported on Scala 3.

The other twist is that boolean options were tweaked so they don’t necessarily default to false. (I think that is confusing.) I don’t know how that interacts with “respect if they disable it”.

I agree that -Xlint:-deprecation,_ is useful syntax, since the idea is that they can add options to -Xlint which you want to accept, but there’s just one you know you want to turn off (deprecation).


Right, fair enough if it’s still a bit in flux.

To give some further input on our shop tends to want to use this: We have a House Rules plugin which just plops in -Wunused:all (and similar “turn all the lints on” options) and expects individual builds to turn off specific options they don’t need (or simply cannot compile with e.g. for generated code). This means that our plugin can just say: "Oh, you’re on 3.3.0 or later, just turn on -Wunused:all and we don’t have to worry about updating the plugin when e.g. 3.3.1 comes out.) I guess we’ll have to revert to the ‘list everything as individual options’ for now and just maintain that list meticulously going forward.

Regarding a model: My mental model has always been (roughly) that the global set of compiler settings was basically a Monoid where each individual field itself could have a sensible Monoid instance. Then all option handling basically just collapses to combine/mappend. (And ‘magic’ flags like ‘all’ don’t really have to do much – just create an instance of the settings with all the relevant bits set to whatever and then combine/mappend.) This should also work pretty well if deferring to defaults just by wrapping in Option as necessary until at definitive value is truly required.

Aha, I see now – sorry for misinterpreting what you needed. Maintaining a “positive” list of opt-in rather than opt-in-all and a “negative” list, seems the way to go for now.

I agree that the help text by -W could help more on how to disable, and it is a bit confusing. Perhaps, you want to open an issue on this (if it’s not already there).