Tracking issue for future-incompatibility lint `forbidden_lint_groups`
Opened this issue · 12 comments
This is the summary issue for the forbidden_lint_groups
future-compatibility warning and other related errors. The goal of
this page is describe why this change was made and how you can fix
code that is affected by it. It also provides a place to ask questions
or register a complaint if you feel the change should not be made. For
more information on the policy around future-compatibility warnings,
see our breaking change policy guidelines.
What is the warning for?
Due to a compiler bug, applying forbid to lint groups,
previously had no effect. The bug is now fixed but instead of
enforcing forbid we issue this future-compatibility warning
to avoid breaking existing crates.
Recommendations
If your crate is using #![forbid(warnings)], we recommend that you change to #![deny(warnings)].
When will this warning become a hard error?
At the beginning of each 6-week release cycle, the Rust compiler team
will review the set of outstanding future compatibility warnings and
nominate some of them for Final Comment Period. Toward the end of
the cycle, we will review any comments and make a final determination
whether to convert the warning into a hard error or remove it
entirely.
Once this is a hard error...
... we can possibly clean up #67885, since maybe flags and attributes can share the same logic then?
I'm not 100% sure this is the right place to report this but the error caused by this change is extremely hard to understand:
warning: allow(unreachable_code) incompatible with previous forbid
--> src/lib.rs:197:9
|
17 | #![forbid(warnings)]
| -------- `forbid` level set here
...
197 | world.repo.publish_offramp(&id, false, o).await?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
While this hints at this issue is in no way provides the information that it is caused by using #![forbid(warnings)] instead of #![deny(warnings)]
Would it be possible to make this error a bit more "rust-like"? E.g. help: use #![deny(warnings)] instead or similar?
The warning message for this is not very helpful.
The following code:
#![forbid(unsafe_code, future_incompatible)]
#![warn(
missing_debug_implementations,
rust_2018_idioms,
trivial_casts,
unused_qualifications
)]Produces:
warning: warn(rust_2018_idioms) incompatible with previous forbid
--> src/lib.rs:4:5
|
1 | #![forbid(unsafe_code, future_incompatible)]
| ------------------- `forbid` level set here
...
4 | rust_2018_idioms,
| ^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
And frankly between that and this issue I am not sure what I am supposed to do?
Am I supposed to turn rust_2018_idioms into it's dependent lints? Does one conflict with future_incompatible? Am I no longer allowed to forbid(future_incompatible)? It isn't clear.
Am I just tired or is this an oversight? Running the following clippy command results in the warnings generated in the followed code block:
$ cargo clippy -- -F warnings -W future-incompatiblewarning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:109:29
|
109 | let target_binary = fs::read(target_file)?;
| ^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
= note: `-W forbidden-lint-groups` implied by `-W future-incompatible`
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:125:26
|
125 | let elf_object = object::File::parse(&*target_binary)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:137:13
|
137 | disassemble_binary(elf_object, capstone_object)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:66:24
|
66 | let section_text = elf_object
| ________________________^
67 | | .section_by_name(".text")
68 | | .ok_or("unable to get the `.text` section from the provided binary")?;
| |_____________________________________________________________________________^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:70:16
|
70 | let code = section_text.data()?;
| ^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:79:28
|
79 | let mnemonic = instruction
| ____________________________^
80 | | .mnemonic()
81 | | .ok_or("ERROR: unable to get mnemonic")?;
| |________________________________________________________^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: allow(unreachable_code) incompatible with previous forbid
--> src/main.rs:82:28
|
82 | let operands = instruction
| ____________________________^
83 | | .op_str()
84 | | .ok_or("ERROR: unable to get operation operands")?;
| |__________________________________________________________________^ overruled by previous forbid
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
= note: `forbid` lint level was set on command line
warning: `inverse-transpiler` (bin "inverse-transpiler") generated 7 warnings
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Am I reading this right? (Not sarcastic, I'm genuinely asking.) Is clippy complaining that the code block under the lines using the ? operator is unreachable_code because if it fails, the following lines may not be executed?
Is this intended behaviour? If yes, is there a proposed workaround or a better method to handle the errors better than what I am doing?
Edit: Forgot to share the Rust version I am using.
$ rustup toolchain list
stable-x86_64-unknown-linux-gnu (default)
1.62.0-x86_64-unknown-linux-gnu
$ cargo --version
cargo 1.69.0 (6e9a83356 2023-04-12)
$ rustc --version
rustc 1.69.0 (84c898d65 2023-04-16)
$ cargo clippy --version
clippy 0.1.69 (84c898d 2023-04-16)@thefossguy: i had the same warning today and got pointed to this issue: #76053
it seems that this is a rustc bug reporting a warning where there shouldn't be one.
if this issue here gets stabilised then i presume that the bug has to be fixed first so as to not break the code which currently gets the invalid warning?
This and #70819 existed next to each other tracking the same problem for years. :)
Great to hear that there's a future-compat lint here now. I think it's been around long enough so we should turn it into a hard error soon.
@rust-lang/lang this has been a future-compat warning for many years. It's also been tracked as a plain bug independently, in #70819. Any objections to making it a hard error?
We currently have a hole in our forbid handling, where this code fails as expected:
#![forbid(dead_code)]
#![allow(dead_code)]
#![crate_type = "lib"]
fn foo() {}But this code actually gets accepted:
#![forbid(unused)]
#![allow(unused)]
#![crate_type = "lib"]
fn foo() {}This is because unused is a lint group, and thus handled slightly differently.
This issue is tracking fixing that hole, and making both of the above examples behave the same.
#133535 proposes to dial this up to show up in reports, and I propose that in 6 or 12 weeks, we make this a hard error on nightly.
On making it a hard error soon, our vibe was positive on that. Please nominate the PR for that for us.
Findings from the crater run in #133536 (crater report found here):
- 5 true regressions total, that's a very small number. 3 of those are from crates.io, and those are all crates with hardly any downloads. 2 of those crates had their last update >= 4 years ago, the third had its github repo archived this year.
- There's a
Serialize/Deserializederive trait containing someallowthat conflicts withforbid(warnings). I would argueforbid(warnings)is just a pretty bad idea and it doesn't seem to be very common. - Sometimes we just get
error[E0453]: allow(dead_code) incompatible with previous forbidwithout a source span, not entirely sure what is going on there. This occurs when building tests. Could it be that the test harness injects anallow?
I'm a bit confused what the "make it a hard error" next step actually means, and why this FCW is reported in dependencies to begin with.
Usually, in the FCW context, "make it a hard error" means a compiler error (not a warning that would honor --cap-lints) in the cases the FCW previously warned about. Reporting the FCW in dependencies is useful because it gives advance warning to all people whose builds may be broken by the hard error.
But in this case, a hard error seems absurd because that would be much worse breakage than just fixing forbid-on-lint-group to behave consistently (i.e., not be overridden by allow(specific_lint)). The latter is "allowed breakage" thanks to --cap-lints, which also silences the "error" emitted for e.g. #[forbid(dead_code)] #[allow(dead_code)]. So if "let forbid to work as intended" is the goal, then I don't understand why this issue needs the same care and process (FCW-in-deps, crater runs) as FCWs that become hard errors.
I can see from #80988 and #81218 that T-lang originally thought the same ("allowed breakage") but the impact was widespread enough that this was reconsidered. Given how long this has been a FCW, it seems like a safe bet that this is no longer a concern.
Oh, apparently there's one subtlety I missed, though it doesn't affect the outcome. --cap-lints doesn't technically affect the "allow incompatible with previous forbid" error, that one's an actual error and can't be capped. However, --cap-lints still saves the day because... I guess it downgrades any forbid to something weaker, so there's no conflict to report? The following crate gets a hard error (not FCW) without --cap-lints, but compiles just fine (not even a warning!) with --cap-lints deny:
#![forbid(dead_code)]
#![allow(dead_code)]