Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forbid overwritten by later allow on the same "scope level" #70819

Open
RalfJung opened this issue Apr 5, 2020 · 30 comments · Fixed by #77534
Open

forbid overwritten by later allow on the same "scope level" #70819

RalfJung opened this issue Apr 5, 2020 · 30 comments · Fixed by #77534
Assignees
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@RalfJung
Copy link
Member

RalfJung commented Apr 5, 2020

forbid is not honored when it is followed by an allow on the same "scope level". This compiles, but should fail:

#![forbid(unused)]
#![allow(unused)]

fn square(num: i32) -> i32 {
    num * num
}

If we move the allow down to the function level, it fails to compile as expected:

#![forbid(unused)]

#[allow(unused)]
fn square(num: i32) -> i32 {
    num * num
}

The same issue also arises with CLI arguments, which all share the "scope level". That was worked around with in #70918, but once the above is fixed, that hack can likely be removed.

Original description

According to my understanding, the purpose of -F/forbid for lints is that they can not be allowed any more. Thus I would expect that calling rustc with -Funused -Aunused will fail when there is unused code in the file.

However, that is not the case: with that sequence of arguments, unused code is silently accepted.

Cc Manishearth/compiletest-rs#216

@RalfJung RalfJung added the C-bug Category: This is a bug. label Apr 5, 2020
@RalfJung
Copy link
Member Author

RalfJung commented Apr 5, 2020

This is in fact a stable-to-beta regression: with Rust 1.42, the code still gets rejected as expected.

@jonas-schievink jonas-schievink added A-frontend Area: Compiler frontend (errors, parsing and HIR) A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. I-nominated regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 5, 2020
@RalfJung
Copy link
Member Author

RalfJung commented Apr 5, 2020

Likely regression candidate: #67885

@RalfJung
Copy link
Member Author

RalfJung commented Apr 5, 2020

Interestingly, doing the same via flags in the source code also does not work as expected -- the allow overwrites the forbid!

#![forbid(unused)]
#![allow(unused)]

fn square(num: i32) -> i32 {
    num * num
}

This is also a regression, but not a recent one: with Rust 1.20, the code gets rejected as expected; with Rust 1.21 and later it gets accepted. It is also in direct contradiction with the documentation which says

'forbid' is a special lint level that's stronger than 'deny'. It's the same as 'deny' in that a lint at this level will produce an error, but unlike the 'deny' level, the 'forbid' level can not be overridden to be anything lower than an error.

@spastorino
Copy link
Member

According to @RalfJung this has possibly regressed on #67885.
I guess this needs confirmation ...

@rustbot ping cleanup

@rustbot rustbot added the ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections label Apr 8, 2020
@rustbot
Copy link
Collaborator

rustbot commented Apr 8, 2020

Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
"Cleanup ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @AminArria @chrissimpkins @contrun @DutchGhost @elshize @ethanboxx @h-michael @HallerPatrick @hdhoang @hellow554 @imtsuki @jakevossen5 @kanru @KarlK90 @LeSeulArtichaut @MAdrianMattocks @matheus-consoli @mental32 @nmccarty @Noah-Kennedy @pard68 @PeytonT @pierreN @Redblueflame @RobbieClarken @RobertoSnap @robjtede @SarthakSingh31 @senden9 @shekohex @sinato @spastorino @turboladen @woshilapin @yerke

@spastorino
Copy link
Member

Assigning P-medium and removing nomination. This was discussed as part of pre-triage meeting in Zulip.

@spastorino spastorino added P-medium Medium priority and removed I-nominated labels Apr 8, 2020
@spastorino
Copy link
Member

spastorino commented Apr 8, 2020

@spastorino spastorino added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Apr 8, 2020
@RalfJung
Copy link
Member Author

RalfJung commented Apr 8, 2020

Note that there are two separate regressions going on:

@AminArria
Copy link
Contributor

Bisect of CLI arguments:

searched nightlies: from nightly-2020-02-04 to nightly-2020-02-18
regressed nightly: nightly-2020-02-17
searched commits: from 61d9231 to 5e7af46
regressed commit: 5e7af46

Indeed it seems the issue comes from #67885

@tobithiel
Copy link
Contributor

I opened #70918 to address the CLI argument regression

@AminArria
Copy link
Contributor

Bisect of inline attributes:

searched toolchains nightly-2017-07-27 through nightly-2017-10-09
regression in nightly-2017-08-11

Checking for commit hashes in that nightly and the one before

$> rustc +nightly-2017-08-11 -vV
rustc 1.21.0-nightly (13d94d5fa 2017-08-10)
binary: rustc
commit-hash: 13d94d5fa8129a34f5c77a1bcd76983f5aed2434

$> rustc +nightly-2017-08-10 -vV
rustc 1.21.0-nightly (f14249953 2017-08-09)
binary: rustc
commit-hash: f142499539d038ef60f4e22cafe11ecdd8a29a1d

Commits by bors in that range:

$> git log --author=bors --format=oneline f142499539d038ef60f4e22cafe11ecdd8a29a1d..13d94d5fa8129a34f5c77a1bcd76983f5aed2434
13d94d5fa8129a34f5c77a1bcd76983f5aed2434 Auto merge of #43559 - Nashenas88:nll-region-renumberer, r=arielb1
b6179602bea71607a9ea63197eca423fcce5f7b0 Auto merge of #43720 - pornel:staticconst, r=petrochenkov
2400ebfe76225745d1591c8a63c54570174ab22c Auto merge of #43522 - alexcrichton:rewrite-lints, r=michaelwoerister
d21ec9b4efd1da012979b050bc0a0426fe45fcdf Auto merge of #43582 - ivanbakel:unused_mut_ref, r=arielb1
2ac5f7d249e29ee48737359e0e6dd9e59701a568 Auto merge of #43737 - GuillaumeGomez:duplicate-method, r=eddyb
16268a88fc0cfe3657439139c63913ffb904b2fa Auto merge of #43735 - est31:master, r=alexcrichton
57e720d2cd09b6befc5b6eed66b65352fc9ff537 Auto merge of #43730 - nrc:driver-shim, r=eddyb
875bcf5c5f7efcbf72e000d256b24293555edf53 Auto merge of #43627 - Aaronepower:master, r=alexcrichton

Centril added a commit to Centril/rust that referenced this issue Apr 9, 2020
…vidtwco

rustc_session: forbid lints override regardless of position

Addresses the regression reported in rust-lang#70819 for command line arguments, but does not address the source code flag regression.
@RalfJung
Copy link
Member Author

RalfJung commented Apr 9, 2020

@AminArria thanks a lot! I would guess the most likely regression candidate is #43522, then.

My guess would be that somewhere around here, lint groups are not handled properly. This code looks different from the previous forbid handling, though why one would treat lint groups properly and one would not is beyond me.

Cc @alexcrichton @michaelwoerister (PR author and reviewer)... but this is from 2017 so I doubt they will remember many details. ;) Cc @rust-lang/wg-diagnostics for people with lint knowledge.

@alexcrichton
Copy link
Member

I'm not sure I have a ton to add here myself, this definitely feels like a bug (both CLI and attribute handling) and seems reasonable to fix, and the fix is likely the same for both.

@RalfJung
Copy link
Member Author

Turns out the problem is not about lint groups, it is about forbid being on the same "scope level" as allow. The following behaves as expected (i.e., it fails to compile):

#![forbid(unused)]

#[allow(unused)]
fn square(num: i32) -> i32 {
    num * num
}

@RalfJung RalfJung changed the title "-Funused" is overwritten by later "-Aunused" forbid overwritten by later allow on the same "scope level" Apr 10, 2020
@RalfJung RalfJung added the regression-from-stable-to-stable Performance or correctness regression from one stable version to another. label May 22, 2020
tmandry added a commit to tmandry/rust that referenced this issue Aug 18, 2020
…ide-forbid-in-same-scope, r=petrochenkov

Disallow later override of forbid lint in same scope

Fix rust-lang#70819

When building lint specs map for a given scope, check if forbid present on each insert.

Drive-by changes:

  1. make `LintLevelsBuilder::push` private to the crate.

  2. Add methods to `LintSource` for extracting its name symbol or its span.

  3. Rewrote old test so that its use of lint attributes are consistent with what we want in the language. (Note that the fact this test existed is a slight sign that we may need a crater run on this bugfix...)
tmandry added a commit to tmandry/rust that referenced this issue Aug 19, 2020
…ide-forbid-in-same-scope, r=petrochenkov

Disallow later override of forbid lint in same scope

Fix rust-lang#70819

When building lint specs map for a given scope, check if forbid present on each insert.

Drive-by changes:

  1. make `LintLevelsBuilder::push` private to the crate.

  2. Add methods to `LintSource` for extracting its name symbol or its span.

  3. Rewrote old test so that its use of lint attributes are consistent with what we want in the language. (Note that the fact this test existed is a slight sign that we may need a crater run on this bugfix...)
tmandry added a commit to tmandry/rust that referenced this issue Aug 19, 2020
…ide-forbid-in-same-scope, r=petrochenkov

Disallow later override of forbid lint in same scope

Fix rust-lang#70819

When building lint specs map for a given scope, check if forbid present on each insert.

Drive-by changes:

  1. make `LintLevelsBuilder::push` private to the crate.

  2. Add methods to `LintSource` for extracting its name symbol or its span.

  3. Rewrote old test so that its use of lint attributes are consistent with what we want in the language. (Note that the fact this test existed is a slight sign that we may need a crater run on this bugfix...)
@petrochenkov
Copy link
Contributor

The PR fixing this (#73379) was closed due to inactivity.
Could someone rebase it, update clippy tests and resubmit?

@Mark-Simulacrum
Copy link
Member

I can do that.

@bors bors closed this as completed in bc600c3 Oct 6, 2020
flip1995 pushed a commit to flip1995/rust that referenced this issue Oct 9, 2020
…w-override-forbid-in-same-scope, r=petrochenkov

Disallow overriding forbid in same scope

Rebased rust-lang#73379.

Fixes rust-lang#70819.
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Nov 14, 2020
Previously, cap-lints was ignored when checking the previous forbid level, which
meant that it was a hard error to do so. This is different from the normal
behavior of lints, which are silenced by cap-lints; if the forbid would not take
effect regardless, there is not much point in complaining about the fact that we
are reducing its level.

It might be considered a bug that even `--cap-lints deny` would suffice to
silence the error on overriding forbid, depending on if one cares about failing
the build or precisely forbid being set. But setting cap-lints to deny is quite
odd and not really done in practice, so we don't try to handle it specially.

This also unifies the code paths for nested and same-level scopes. However, the
special case for CLI lint flags is left in place (introduced by rust-lang#70918) to fix
the regression noted in rust-lang#70819. That means that CLI flags do not lint on forbid
being overridden by a non-forbid level. It is unclear whether this is a bug or a
desirable feature, but it is certainly inconsistent. CLI flags are a
sufficiently different "type" of place though that this is deemed out of scope
for this commit.
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 2, 2020
…kfelix

Use true previous lint level when detecting overriden forbids

Previously, cap-lints was ignored when checking the previous forbid level, which
meant that it was a hard error to do so. This is different from the normal
behavior of lints, which are silenced by cap-lints; if the forbid would not take
effect regardless, there is not much point in complaining about the fact that we
are reducing its level.

It might be considered a bug that even `--cap-lints deny` would suffice to
silence the error on overriding forbid, depending on if one cares about failing
the build or precisely forbid being set. But setting cap-lints to deny is quite
odd and not really done in practice, so we don't try to handle it specially.

This also unifies the code paths for nested and same-level scopes. However, the
special case for CLI lint flags is left in place (introduced by rust-lang#70918) to fix
the regression noted in rust-lang#70819. That means that CLI flags do not lint on forbid
being overridden by a non-forbid level. It is unclear whether this is a bug or a
desirable feature, but it is certainly inconsistent. CLI flags are a
sufficiently different "type" of place though that this is deemed out of scope
for this commit.

r? `@pnkfelix` perhaps?

cc rust-lang#77713 -- not marking as "Fixes" because of the lack of proper unused attribute handling in this PR
@SparrowLii
Copy link
Member

@RalfJung The FIXME here links to this closed issue. I think it can be removed?

@RalfJung
Copy link
Member Author

RalfJung commented May 10, 2021

Maybe? It is worth trying, but I don't know that code very well.

EDIT: By "it" I mean removing the usize::MAX hack, not just the FIXME comment.

@FabianWolff
Copy link
Contributor

Unfortunately not, it seems. With the following input file:

fn main() {
    let a = 5;
}

I get, on current nightly with -F unused -A unused:

error: unused variable: `a`
 --> t1.rs:2:9
  |
2 |     let a = 5;
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `-F unused-variables` implied by `-F unused`

error: aborting due to previous error

which is actually suboptimal, because there is no warning about the -A being overwritten by the -F (with crate attributes #![forbid(unused)] and #![allow(unused)], there is a warning, and it even mentions that this will become a hard error in the future).

In any case, with the following patch applied and the same command line arguments:

diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f517c483758..436afad11b8 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1161,15 +1161,7 @@ pub fn get_cmd_lint_options(
     let mut describe_lints = false;
 
     for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
-        for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
-            let arg_pos = if let lint::Forbid = level {
-                // HACK: forbid is always specified last, so it can't be overridden.
-                // FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
-                // fixed and `forbid` works as expected.
-                usize::MAX
-            } else {
-                passed_arg_pos
-            };
+        for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
             if lint_name == "help" {
                 describe_lints = true;
             } else {

I get no warnings and no errors (incorrectly, because -F should not be overwritten by -A).

@RalfJung
Copy link
Member Author

I get no warnings and no errors (incorrectly, because -F should not be overwritten by -A).

Yeah that's wrong... so the FIXME is still accurate, though I am not sure why.

@nikomatsakis
Copy link
Contributor

I'm going to briefly re-open this issue -- I don't remember what we decided about -F and -A, but I bet @Mark-Simulacrum does =)

@pnkfelix
Copy link
Member

pnkfelix commented Dec 16, 2022

Arguably this shouldn't be assigned to me anymore.

Its possible we may want to close this and open a fresh issue (potentially a P-medium one, or just freshly re-prioritized) dedicated to the command line interactions between -F and -A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet