Skip to content

Conversation

@lrytz
Copy link
Member

@lrytz lrytz commented Aug 26, 2019

This PR adds a -Wconf compiler flag that allows filtering and configuring compiler warnings (silence them, or turn them into errors).

It also integrates the fantastic silencer compiler plugin by @ghik into the compiler, which allows suppressing warnings locally using the @nowarn annotation.

Configurable Warnings

Warnings are assigned a category.

Warnings can be filtered by category, by message regex, by site where they are issued, and by source path. Deprecations can additionally be filtered by origin (deprecated definition) and since version.

Filtered warnings can be reported as error, warning, info, summary (like deprecations) or silent.

Local Suppression

The @nowarn annotation suppresses warnings within the scope covered by the annotation.

  • @nowarn def foo = ..., @nowarn class C { ... }: suppress warnings in a definition
  • expression: @nowarn: suppress warnings in a specific expression

The annotation can be configured to filter selected warnings, for example @nowarn("cat=deprecation") only suppresses deprecation warnings. The filter configuration syntax is the same as in -Wconf.

Help Text

$> scalac -Wconf:help
Configure compiler warnings.
Syntax: -Wconf:<filters>:<action>,<filters>:<action>,...
multiple <filters> are combined with &, i.e., <filter>&...&<filter>

Note: Run with `-Wconf:any:warning-verbose` to print warnings with their category, site,
and (for deprecations) origin and since-version.

<filter>
  - Any message: any

  - Message categories: cat=deprecation, cat=lint, cat=lint-infer-any
    The full list of warning categories is shown at the end of this help text.

  - Message content: msg=regex
    The regex need only match some part of the message, not all of it.

  - Site where the warning is triggered: site=my\.package\..*
    The regex must match the full name (`package.Class.method`) of the warning position.

  - Source file name: src=src_managed/.*
    If `-rootdir` is specified, the regex must match the canonical path relative to the
    root directory. Otherwise, the regex must match the canonical path relative to any
    path segment (`b/.*Test.scala` matches `/a/b/XTest.scala` but not `/ab/Test.scala`).
    Use unix-style paths, separated by `/`.

  - Origin of deprecation: origin=external\.package\..*
    The regex must match the full name (`package.Class.method`) of the deprecated entity.

  - Since of deprecation: since<1.24
    Valid operators: <, =, >, valid versions: N, N.M, N.M.P. Compares against the first
    version of the form N, N.M or N.M.P found in the `since` parameter of the deprecation,
    for example `1.2.3` in `@deprecated("", "some lib 1.2.3-foo")`.

<action>
  - error / e
  - warning / w
  - warning-summary / ws (summary with the number of warnings, like for deprecations)
  - warning-verbose / wv (show warning category and site)
  - info / i             (infos are not counted as warnings and don't affect `-Werror`)
  - info-summary / is
  - info-verbose / iv
  - silent / s

The default configuration is:
  -Wconf:cat=deprecation:ws,cat=feature:ws,cat=optimizer:ws

User-defined configurations are added to the left. The leftmost rule matching
a warning message defines the action.

Examples:
  - change every warning into an error: -Wconf:any:error
  - silence certain deprecations: -Wconf:origin=some\.lib\..*&since>2.2:s

Full list of message categories:
 - deprecation
 - feature, feature-dynamics, feature-existentials, feature-higher-kinds, feature-implicit-conversions, feature-macros, feature-postfix-ops, feature-reflective-calls
 - java-source
 - lint, lint-adapted-args, lint-byname-implicit, lint-constant, lint-delayedinit-select, lint-deprecation, lint-doc-detached, lint-eta-sam, lint-eta-zero, lint-implicit-not-found, lint-inaccessible, lint-infer-any, lint-missing-interpolator, lint-nonlocal-return, lint-nullary-override, lint-nullary-unit, lint-option-implicit, lint-package-object-classes, lint-poly-implicit-overload, lint-private-shadow, lint-recurse-with-default, lint-serial, lint-stars-align, lint-type-parameter-shadow, lint-unit-specialization
 - optimizer
 - other, other-debug, other-match-analysis, other-migration, other-pure-statement, other-shadowing
 - scaladoc
 - unchecked
 - unused, unused-imports, unused-locals, unused-nowarn, unused-params, unused-pat-vars, unused-privates
 - w-flag, w-flag-dead-code, w-flag-extra-implicit, w-flag-numeric-widen, w-flag-self-implicit, w-flag-value-discard

To suppress warnings locally, use the `scala.annotation.nowarn` annotation.

Note: on the command-line you might need to quote configurations containing `*` or `&`
to prevent the shell from expanding patterns.

Significant changes

  • What's described above in the PR description
  • MiMa exception for addition of scala.annotation.nowarn
  • Adds a -rootdir compiler flag. It is used to relativize file paths when using source filters (-Wconf:src=some/source/File.scala:s), there might be other uses for it in the future.
  • Compiler API changes
    • warning methods in currentRun.reporting and context reporter take new Category parameter. The global.reporter is unchanged, warnings reported through it are not filtered by Wconf.
    • Removed a few deprecated methods (compilationUnit.error/warning)
  • Reporting warnings is now delayed until after typer, because the typer collects @nowarn annotations.
  • If we stop before typer (e.g., because there are errors in the parser), all warnings are shown, even if they are enclosed in @nowarn
  • If a phase before typer has both errors and warnings, all errors are printed before the warnings.
  • Unchecked warnings are now all shown by default (they were summarized like deprecations before)
  • The -deprecation, -feature and -unchecked settings are no longer directly used in the compiler, they are shortcuts for specific Wconf configurations. the compiler only looks at -Wconf.

@scala-jenkins scala-jenkins added this to the 2.13.2 milestone Aug 26, 2019
@lrytz lrytz added the WIP label Aug 26, 2019
@lrytz
Copy link
Member Author

lrytz commented Aug 26, 2019

Message filtering is performed in global.currentRun.reporting, not in the Global.reporter.

The reasons are:

  • Separation of concerns: Reporters worry about how to do reporting, removing duplicate messages.
  • Custom Reporters are used by sbt, silencer, REPL, etc. It's too hard to do the necessary changes to the Reporter interface.
  • The Wconf setting could change between compiler runs. currentRun.reporting respects those changes.

So all warnings in the compiler should go through global.runReporting (which is the same as global.currentRun.reporting). This method takes four parameters: pos, msg, category (new), site (new). The site is usually context.owner (in the frontend) or currentOwner (in transformations).

Context has a warn method with 3 parameters (pos, msg, category) and inserts the owner as site, so this is used in the frontend (context reporters are also used to support silent mode / trying twice).

The global.warning method is deprecated and no longer used.

There are a few calls to Reporter.warning left in the codebase where no runReporting is reachable, I think they are aoll OK not to categorize / allow filtering. E.g., when running Scaladoc

    else if (docSettings.showPlugins.value)
      reporter.warning(null, "Plugins are not available when using Scaladoc")

@lrytz
Copy link
Member Author

lrytz commented Sep 5, 2019

Added support for local warning suppression using @silent. I borrowed heavily from silencer, in design, implementation and tests; cc @ghik, a huge THANK YOU for your work!

@ijuma
Copy link
Contributor

ijuma commented Sep 5, 2019

This will be immensely useful. Thanks for working on this!

@lrytz lrytz force-pushed the confwarn branch 4 times, most recently from 7729d15 to 9c37e5e Compare September 9, 2019 12:25
@lrytz lrytz changed the title Wconf flag for configurable warnings [ci: last-only] Wconf flag for configurable warnings, @silent for local suppression [ci: last-only] Sep 9, 2019
@lrytz lrytz removed the WIP label Sep 9, 2019
@lrytz
Copy link
Member Author

lrytz commented Sep 9, 2019

Removed the WIP flag and update the PR description, this is ready to be reviewed!

@lrytz lrytz force-pushed the confwarn branch 3 times, most recently from 174a43e to 8aa1750 Compare September 23, 2019 12:10
@lrytz
Copy link
Member Author

lrytz commented Sep 23, 2019

@SethTisue would you be interested to review this, at least on a high level? I updated the PR description, and also included a section on significant changes.

@SethTisue SethTisue self-requested a review September 23, 2019 14:27
@lrytz lrytz force-pushed the confwarn branch 2 times, most recently from f2ed6db to 1667f83 Compare September 27, 2019 08:54
@ijuma
Copy link
Contributor

ijuma commented Apr 2, 2020

@lrytz Thanks for the quick response.

scala-collection-compat would be perfect, we already use it for other reasons.

I got site to work with the help from your example. I got confused because the help text in the PR description shows a \ before the .:

image

@lrytz
Copy link
Member Author

lrytz commented Apr 2, 2020

OK, I see how the \ can be annoying to get right... The thing is, the pattern is a java regex, so if you write site=my.pack.*, it matches myApack.

The following command line worked as expected for me:

scv 2.13.2-bin-cd56924 '-Wconf:site=a\.pu\.K\.f:s,cat=deprecation:wv' Test.scala

@ijuma
Copy link
Contributor

ijuma commented Apr 2, 2020

@lrytz I investigated more and I found the issue. I got a bit unlucky and the first warning I tried to suppress didn't seem to have the @ location captured correctly:

"Error:(109, 68) [unused-params @ ] parameter value nn in method body is never used
def body[T <: AbstractRequest](implicit classTag: ClassTag[T], nn: NotNothing[T]): T = {"

In the Kafka codebase, we had one other example like the above (similar pattern), but all other ones worked fine. The usage of wv from your example helped track this down.

@lrytz
Copy link
Member Author

lrytz commented Apr 2, 2020

I'll take a look if I can reproduce and fix that.

For @nowarn, I submitted scala/scala-collection-compat#312

@lrytz
Copy link
Member Author

lrytz commented Apr 3, 2020

(moved my comment to scala/scala-collection-compat#312 (comment) where I intended to post it)

@lrytz
Copy link
Member Author

lrytz commented Apr 3, 2020

@ijuma #8852 fixes the warning site for unused warnings.

@ijuma
Copy link
Contributor

ijuma commented Apr 3, 2020

Thanks!

@charpov
Copy link
Contributor

charpov commented Sep 28, 2020

comparing a fresh object using `eq` will always yield false is being suppressed by @nowarn("cat=other") but not by any of the other- subcategories I have tried. Is there one that is missing from the documentation?

@som-snytt
Copy link
Contributor

som-snytt commented Sep 29, 2020

@charpov https://github.com/scala/scala/blob/v2.13.3/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala#L1046 just says other. (Probably I'd ask on gitter instead of the old PR.) (or the forum. It might be a useful topic to consider what cats are useful.)

hamzaremmal pushed a commit to hamzaremmal/scala3 that referenced this pull request May 2, 2025
add -Wconf flag for configurable warnings, @nowarn annotation for local suppression
hamzaremmal pushed a commit to scala/scala3 that referenced this pull request May 7, 2025
add -Wconf flag for configurable warnings, @nowarn annotation for local suppression
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes worth highlighting in next release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.