TLDR
I'd like to discuss a design for defining exceptions to the -warnings-as-errors
rule.
Background
There is a lack of flexibility in how the compiler can be configured to deal with warnings. Specifically, when the -warnings-as-errors
option is enabled, all warnings are treated as errors unless the -no-warnings-as-errors
option is also applied, which turns off the rule completely.
Although having -warnings-as-errors
enabled is a good hygiene practice, it also has some downsides when it comes to compiler and SDK updates.
The most obvious example is when a function or type is declared deprecated in an update. Additionally, there are the new concurrency diagnostics introduced in versions 5.9, 5.10, and probably 6.0. There are many more examples as well.
The problem escalates as the codebase grows. In some projects, the people responsible for the code and those responsible for the infrastructure are different groups. When it comes to a compiler update, the infrastructure team can sometimes face an overwhelming amount of work to address all the newly diagnosed warnings at once.
Proposed solution
I propose a new compiler option -no-warning-as-error
, which allows users to specify exceptions to the -warnings-as-errors
option.
Originally, the format of the option was -no-warning-as-error <diag_id>
, where <diag_id>
is one of the diagnostic IDs listed in include/swift/AST/Diagnostics*.def
.
However, @ArtemC and @Douglas_Gregor rightfully pointed out that the diagnostic IDs aren't stable and will never be stable, as the compiler continuously improves diagnostics and introduces more specific versions for existing messages, necessitating the creation of new diagnostic IDs.
So instead it was suggested to follow Clang's model of diagnostic groups whose name are stable across the compiler's versions. And then sort all the existing warnings into these groups.
For example, these two warnings can be grouped into a single group named ignored_import
:
WARNING(sema_import_current_module,none,
"this file is part of module %0; ignoring import", (Identifier))
WARNING(sema_import_current_module_with_file,none,
"file '%0' is part of module %1; ignoring import",
(StringRef, Identifier))
Both of these warnings can then be exempted from being upgraded to errors by specifying -no-warning-as-error ignored_import
.
It's a lot of work
It would require grouping hundreds of warnings and errors into appropriate groups and properly naming these groups. This process involves considerable work, verification, and approval, which may be too much to accomplish all at once.
So I think it'd be more approachable to do this gradually:
-
Introduce support for group names
- Create two versions of the
WARNING
andERROR
macros: one with a group name argument and one without. - Address some of the most popular warnings first.
- Implement support for the
-no-warning-as-error <group_name>
option.
- Create two versions of the
-
Temporary Support for Diagnostic IDs
- Implement a temporary special syntax for the remaining warnings:
-no-warning-as-error _id:<diag_id>
, which accepts diagnostic IDs as declared in theDiagnostics*.def
files. - Note that this syntax will not be stable and should not be used in build settings for modules built in unknown environments (e.g., distributed libraries). Its existence at all isn't guaranteed either.
- Implement a temporary special syntax for the remaining warnings:
-
Complete the Grouping
- Gradually sort all diagnostic messages into appropriate groups.
- Discard support for the temporary diagnostic ID syntax introduced in Step 2.
- Make the group name parameter mandatory in the
WARNING
andERROR
macros.
The original discussion is in this PR: [Diagnostics] Add -no-warning-as-error to except a specific warning from being treated as an error by DmT021 · Pull Request #74466 · swiftlang/swift · GitHub