diff --git a/text/0000-cap-lints.md b/text/0000-cap-lints.md new file mode 100644 index 00000000000..ce71a1a9537 --- /dev/null +++ b/text/0000-cap-lints.md @@ -0,0 +1,109 @@ +- Feature Name: N/A +- Start Date: 2015-07-07 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Add a new flag to the compiler, `--cap-lints`, which set the maximum possible +lint level for the entire crate (and cannot be overridden). Cargo will then pass +`--cap-lints allow` to all upstream dependencies when compiling code. + +# Motivation + +> Note: this RFC represents issue [#1029][issue] + +Currently any modification to a lint in the compiler is strictly speaking a +breaking change. All crates are free to place `#![deny(warnings)]` at the top of +their crate, turning any new warnings into compilation errors. This means that +if a future version of Rust starts to emit new warnings it may fail to compile +some previously written code (a breaking change). + +We would very much like to be able to modify lints, however. For example +[rust-lang/rust#26473][pr] updated the `missing_docs` lint to also look for +missing documentation on `const` items. This ended up [breaking some +crates][term-pr] in the ecosystem due to their usage of +`#![deny(missing_docs)]`. + +[issue]: https://github.com/rust-lang/rfcs/issues/1029 +[pr]: https://github.com/rust-lang/rust/pull/26473 +[term-pr]: https://github.com/rust-lang/term/pull/34 + +The mechanism proposed in this RFC is aimed at providing a method to compile +upstream dependencies in a way such that they are resilient to changes in the +behavior of the standard lints in the compiler. A new lint warning or error will +never represent a memory safety issue (otherwise it'd be a real error) so it +should be safe to ignore any new instances of a warning that didn't show up +before. + +# Detailed design + +There are two primary changes propsed by this RFC, the first of which is a new +flag to the compiler: + +``` + --cap-lints LEVEL Set the maximum lint level for this compilation, cannot + be overridden by other flags or attributes. +``` + +For example when `--cap-lints allow` is passed, all instances of `#[warn]`, +`#[deny]`, and `#[forbid]` are ignored. If, however `--cap-lints warn` is passed +only `deny` and `forbid` directives are ignored. + +The acceptable values for `LEVEL` will be `allow`, `warn`, `deny`, or `forbid`. + +The second change proposed is to have Cargo pass `--cap-lints allow` to all +upstream dependencies. Cargo currently passes `-A warnings` to all upstream +dependencies (allow all warnings by default), so this would just be guaranteeing +that no lints could be fired for upstream dependencies. + +With these two pieces combined together it is now possible to modify lints in +the compiler in a backwards compatible fashion. Modifications to existing lints +to emit new warnings will not get triggered, and new lints will also be entirely +suppressed **only for upstream dependencies**. + +## Cargo Backwards Compatibility + +This flag would be first non-1.0 flag that Cargo would be passing to the +compiler. This means that Cargo can no longer drive a 1.0 compiler, but only a +1.N+ compiler which has the `--cap-lints` flag. To handle this discrepancy Cargo +will detect whether `--cap-lints` is a valid flag to the compiler. + +Cargo already runs `rustc -vV` to learn about the compiler (e.g. a "unique +string" that's opaque to Cargo) and it will instead start passing +`rustc -vV --cap-lints allow` to the compiler instead. This will allow Cargo to +simultaneously detect whether the flag is valid and learning about the version +string. If this command fails and `rustc -vV` succeeds then Cargo will fall back +to the old behavior of passing `-A warnings`. + +# Drawbacks + +This RFC adds surface area to the command line of the compiler with a relatively +obscure option `--cap-lints`. The option will almost never be passed by anything +other than Cargo, so having it show up here is a little unfortunate. + +Some crates may inadvertently rely on memory safety through lints, or otherwise +very much not want lints to be turned off. For example if modifications to a new +lint to generate more warnings caused an upstream dependency to fail to compile, +it could represent a serious bug indicating the dependency needs to be updated. +This system would paper over this issue by forcing compilation to succeed. This +use case seems relatively rare, however, and lints are also perhaps not the best +method to ensure the safety of a crate. + +Cargo may one day grow configuration to *not* pass this flag by default (e.g. go +back to passing `-Awarnings` by default), which is yet again more expansion of +API surface area. + +# Alternatives + +* Modifications to lints or additions to lints could be considered + backwards-incompatible changes. +* The meaning of the `-A` flag could be reinterpreted as "this cannot be + overridden" +* A new "meta lint" could be introduced to represent the maximum cap, for + example `-A everything`. This is semantically different enough from `-A foo` + that it seems worth having a new flag. + +# Unresolved questions + +None yet.