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 #70918) to fix
the regression noted in #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.
id: LintId,
(level, src): LevelSource,
) {
- if let Some((old_level, old_src)) = specs.get(&id) {
- if old_level == &Level::Forbid && level != Level::Forbid {
+ // Setting to a non-forbid level is an error if the lint previously had
+ // a forbid level. Note that this is not necessarily true even with a
+ // `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
+ //
+ // This means that this only errors if we're truly lowering the lint
+ // level from forbid.
+ if level != Level::Forbid {
+ if let (Level::Forbid, old_src) =
+ self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess)
+ {
let mut diag_builder = struct_span_err!(
self.sess,
src.span(),
E0453,
- "{}({}) incompatible with previous forbid in same scope",
+ "{}({}) incompatible with previous forbid",
level.as_str(),
src.name(),
);
- match *old_src {
- LintSource::Default => {}
+ diag_builder.span_label(src.span(), "overruled by previous forbid");
+ match old_src {
+ LintSource::Default => {
+ diag_builder.note(&format!(
+ "`forbid` lint level is the default for {}",
+ id.to_string()
+ ));
+ }
LintSource::Node(_, forbid_source_span, reason) => {
diag_builder.span_label(forbid_source_span, "`forbid` level set here");
if let Some(rationale) = reason {
}
}
diag_builder.emit();
+
+ // Retain the forbid lint level
return;
}
}
}
}
- for (id, &(level, ref src)) in specs.iter() {
- if level == Level::Forbid {
- continue;
- }
- let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
- (Some(Level::Forbid), src) => src,
- _ => continue,
- };
- let forbidden_lint_name = match forbid_src {
- LintSource::Default => id.to_string(),
- LintSource::Node(name, _, _) => name.to_string(),
- LintSource::CommandLine(name, _) => name.to_string(),
- };
- let (lint_attr_name, lint_attr_span) = match *src {
- LintSource::Node(name, span, _) => (name, span),
- _ => continue,
- };
- let mut diag_builder = struct_span_err!(
- self.sess,
- lint_attr_span,
- E0453,
- "{}({}) overruled by outer forbid({})",
- level.as_str(),
- lint_attr_name,
- forbidden_lint_name
- );
- diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
- match forbid_src {
- LintSource::Default => {}
- LintSource::Node(_, forbid_source_span, reason) => {
- diag_builder.span_label(forbid_source_span, "`forbid` level set here");
- if let Some(rationale) = reason {
- diag_builder.note(&rationale.as_str());
- }
- }
- LintSource::CommandLine(_, _) => {
- diag_builder.note("`forbid` lint level was set on command line");
- }
- }
- diag_builder.emit();
- // don't set a separate error for every lint in the group
- break;
- }
-
let prev = self.cur;
if !specs.is_empty() {
self.cur = self.sets.list.len() as u32;
//~^ WARN use of deprecated attribute `plugin`
#![forbid(test_lint)]
-fn lintme() { } //~ ERROR item is named 'lintme'
+fn lintme() {} //~ ERROR item is named 'lintme'
#[allow(test_lint)]
-//~^ ERROR allow(test_lint) overruled by outer forbid(test_lint)
-//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
-//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+//~^ ERROR allow(test_lint) incompatible
+//~| ERROR allow(test_lint) incompatible
+//~| ERROR allow(test_lint) incompatible
pub fn main() {
lintme();
}
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-attrs.rs:11:9
|
LL | #![forbid(test_lint)]
LL | #[allow(test_lint)]
| ^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-attrs.rs:11:9
|
LL | #![forbid(test_lint)]
error: item is named 'lintme'
--> $DIR/lint-plugin-forbid-attrs.rs:9:1
|
-LL | fn lintme() { }
- | ^^^^^^^^^^^^^^^
+LL | fn lintme() {}
+ | ^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-plugin-forbid-attrs.rs:7:11
LL | #![forbid(test_lint)]
| ^^^^^^^^^
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-attrs.rs:11:9
|
LL | #![forbid(test_lint)]
//~^ WARN use of deprecated attribute `plugin`
fn lintme() { } //~ ERROR item is named 'lintme'
-#[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint)
- //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
- //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+#[allow(test_lint)] //~ ERROR allow(test_lint) incompatible
+ //~| ERROR allow(test_lint) incompatible
+ //~| ERROR allow(test_lint)
pub fn main() {
lintme();
}
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-cmdline.rs:10:9
|
LL | #[allow(test_lint)]
|
= note: `forbid` lint level was set on command line
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-cmdline.rs:10:9
|
LL | #[allow(test_lint)]
|
= note: requested on the command line with `-F test-lint`
-error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+error[E0453]: allow(test_lint) incompatible with previous forbid
--> $DIR/lint-plugin-forbid-cmdline.rs:10:9
|
LL | #[allow(test_lint)]
#![forbid(non_snake_case)]
#[allow(non_snake_case)]
-//~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
-//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
-//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+//~^ ERROR allow(non_snake_case) incompatible
+//~| ERROR allow(non_snake_case) incompatible
+//~| ERROR allow(non_snake_case) incompatible
fn main() {
}
-error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(non_snake_case) incompatible with previous forbid
--> $DIR/E0453.rs:3:9
|
LL | #![forbid(non_snake_case)]
LL | #[allow(non_snake_case)]
| ^^^^^^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(non_snake_case) incompatible with previous forbid
--> $DIR/E0453.rs:3:9
|
LL | #![forbid(non_snake_case)]
LL | #[allow(non_snake_case)]
| ^^^^^^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(non_snake_case) incompatible with previous forbid
--> $DIR/E0453.rs:3:9
|
LL | #![forbid(non_snake_case)]
--- /dev/null
+// check-pass
+// compile-args: --cap-lints=warn -Fwarnings
+
+// This checks that the forbid attribute checking is ignored when the forbidden
+// lint is capped.
+
+#![forbid(warnings)]
+#![allow(unused)]
+
+#[allow(unused)]
+mod bar {
+ fn bar() {}
+}
+
+fn main() {}
fn forbid_first(num: i32) -> i32 {
#![forbid(unused)]
#![deny(unused)]
- //~^ ERROR: deny(unused) incompatible with previous forbid in same scope [E0453]
+ //~^ ERROR: deny(unused) incompatible with previous forbid
#![warn(unused)]
- //~^ ERROR: warn(unused) incompatible with previous forbid in same scope [E0453]
+ //~^ ERROR: warn(unused) incompatible with previous forbid
#![allow(unused)]
- //~^ ERROR: allow(unused) incompatible with previous forbid in same scope [E0453]
+ //~^ ERROR: allow(unused) incompatible with previous forbid
num * num
}
-error[E0453]: deny(unused) incompatible with previous forbid in same scope
+error[E0453]: deny(unused) incompatible with previous forbid
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:19:13
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
LL | #![deny(unused)]
- | ^^^^^^
+ | ^^^^^^ overruled by previous forbid
-error[E0453]: warn(unused) incompatible with previous forbid in same scope
+error[E0453]: warn(unused) incompatible with previous forbid
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
...
LL | #![warn(unused)]
- | ^^^^^^
+ | ^^^^^^ overruled by previous forbid
-error[E0453]: allow(unused) incompatible with previous forbid in same scope
+error[E0453]: allow(unused) incompatible with previous forbid
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:23:14
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
...
LL | #![allow(unused)]
- | ^^^^^^
+ | ^^^^^^ overruled by previous forbid
error: aborting due to 3 previous errors
#![forbid(deprecated)]
#[allow(deprecated)]
-//~^ ERROR allow(deprecated) overruled by outer forbid(deprecated)
-//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
-//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+//~^ ERROR allow(deprecated) incompatible
+//~| ERROR allow(deprecated) incompatible
+//~| ERROR allow(deprecated) incompatible
fn main() {
}
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-attr.rs:3:9
|
LL | #![forbid(deprecated)]
LL | #[allow(deprecated)]
| ^^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-attr.rs:3:9
|
LL | #![forbid(deprecated)]
LL | #[allow(deprecated)]
| ^^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-attr.rs:3:9
|
LL | #![forbid(deprecated)]
// compile-flags: -F deprecated
-#[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
- //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
- //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+#[allow(deprecated)] //~ ERROR allow(deprecated) incompatible
+ //~| ERROR allow(deprecated) incompatible
+ //~| ERROR allow(deprecated) incompatible
fn main() {
}
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-cmdline.rs:3:9
|
LL | #[allow(deprecated)]
|
= note: `forbid` lint level was set on command line
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-cmdline.rs:3:9
|
LL | #[allow(deprecated)]
|
= note: `forbid` lint level was set on command line
-error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+error[E0453]: allow(deprecated) incompatible with previous forbid
--> $DIR/lint-forbid-cmdline.rs:3:9
|
LL | #[allow(deprecated)]
// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See
// Issue #42873.
+// If you turn off deduplicate diagnostics (which rustc turns on by default but
+// compiletest turns off when it runs ui tests), then the errors are
+// (unfortunately) repeated here because the checking is done as we read in the
+// errors, and currently that happens two or three different times, depending on
+// compiler flags.
+//
+// The test is much cleaner if we deduplicate, though.
+
+// compile-flags: -Z deduplicate-diagnostics=yes
+
#![forbid(unused, non_snake_case)]
-#[allow(unused_variables)] //~ ERROR overruled
- //~| ERROR overruled
- //~| ERROR overruled
+#[allow(unused_variables)] //~ ERROR incompatible with previous
fn foo() {}
-#[allow(unused)] //~ ERROR overruled
- //~| ERROR overruled
- //~| ERROR overruled
+#[allow(unused)] //~ ERROR incompatible with previous
fn bar() {}
-#[allow(nonstandard_style)] //~ ERROR overruled
- //~| ERROR overruled
- //~| ERROR overruled
+#[allow(nonstandard_style)] //~ ERROR incompatible with previous
fn main() {
println!("hello forbidden world")
}
-error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:9:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | ------ `forbid` level set here
-LL |
-LL | #[allow(unused_variables)]
- | ^^^^^^^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(unused) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:14:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | ------ `forbid` level set here
-...
-LL | #[allow(unused)]
- | ^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
- --> $DIR/outer-forbid.rs:19:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | -------------- `forbid` level set here
-...
-LL | #[allow(nonstandard_style)]
- | ^^^^^^^^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:9:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | ------ `forbid` level set here
-LL |
-LL | #[allow(unused_variables)]
- | ^^^^^^^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(unused) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:14:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | ------ `forbid` level set here
-...
-LL | #[allow(unused)]
- | ^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(unused_variables) incompatible with previous forbid
--> $DIR/outer-forbid.rs:19:9
|
-LL | #![forbid(unused, non_snake_case)]
- | -------------- `forbid` level set here
-...
-LL | #[allow(nonstandard_style)]
- | ^^^^^^^^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:9:9
- |
LL | #![forbid(unused, non_snake_case)]
| ------ `forbid` level set here
LL |
LL | #[allow(unused_variables)]
| ^^^^^^^^^^^^^^^^ overruled by previous forbid
-error[E0453]: allow(unused) overruled by outer forbid(unused)
- --> $DIR/outer-forbid.rs:14:9
+error[E0453]: allow(unused) incompatible with previous forbid
+ --> $DIR/outer-forbid.rs:22:9
|
LL | #![forbid(unused, non_snake_case)]
| ------ `forbid` level set here
LL | #[allow(unused)]
| ^^^^^^ overruled by previous forbid
-error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
- --> $DIR/outer-forbid.rs:19:9
+error[E0453]: allow(nonstandard_style) incompatible with previous forbid
+ --> $DIR/outer-forbid.rs:25:9
|
LL | #![forbid(unused, non_snake_case)]
| -------------- `forbid` level set here
LL | #[allow(nonstandard_style)]
| ^^^^^^^^^^^^^^^^^ overruled by previous forbid
-error: aborting due to 9 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0453`.
#![feature(lint_reasons)]
+// If you turn off deduplicate diagnostics (which rustc turns on by default but
+// compiletest turns off when it runs ui tests), then the errors are
+// (unfortunately) repeated here because the checking is done as we read in the
+// errors, and currently that happens two or three different times, depending on
+// compiler flags.
+//
+// The test is much cleaner if we deduplicate, though.
+
+// compile-flags: -Z deduplicate-diagnostics=yes
+
#![forbid(
unsafe_code,
//~^ NOTE `forbid` level set here
- //~| NOTE `forbid` level set here
- //~| NOTE `forbid` level set here
- //~| NOTE `forbid` level set here
- //~| NOTE `forbid` level set here
- //~| NOTE `forbid` level set here
+ //~| NOTE the lint level is defined here
reason = "our errors & omissions insurance policy doesn't cover unsafe Rust"
)]
let a_billion_dollar_mistake = ptr::null();
#[allow(unsafe_code)]
- //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
- //~| NOTE overruled by previous forbid
- //~| NOTE overruled by previous forbid
- //~| NOTE overruled by previous forbid
- //~| NOTE overruled by previous forbid
- //~| NOTE overruled by previous forbid
- //~| NOTE overruled by previous forbid
- //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
- //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
- //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
- //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
- //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
+ //~^ ERROR allow(unsafe_code) incompatible with previous forbid
//~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
+ //~| NOTE overruled by previous forbid
unsafe {
+ //~^ ERROR usage of an `unsafe` block
+ //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
*a_billion_dollar_mistake
}
}
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+ --> $DIR/reasons-forbidden.rs:25:13
|
LL | unsafe_code,
| ----------- `forbid` level set here
|
= note: our errors & omissions insurance policy doesn't cover unsafe Rust
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
+error: usage of an `unsafe` block
+ --> $DIR/reasons-forbidden.rs:29:5
|
-LL | unsafe_code,
- | ----------- `forbid` level set here
-...
-LL | #[allow(unsafe_code)]
- | ^^^^^^^^^^^ overruled by previous forbid
- |
- = note: our errors & omissions insurance policy doesn't cover unsafe Rust
-
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
- |
-LL | unsafe_code,
- | ----------- `forbid` level set here
-...
-LL | #[allow(unsafe_code)]
- | ^^^^^^^^^^^ overruled by previous forbid
+LL | / unsafe {
+LL | |
+LL | |
+LL | | *a_billion_dollar_mistake
+LL | | }
+ | |_____^
|
= note: our errors & omissions insurance policy doesn't cover unsafe Rust
-
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
+note: the lint level is defined here
+ --> $DIR/reasons-forbidden.rs:14:5
|
LL | unsafe_code,
- | ----------- `forbid` level set here
-...
-LL | #[allow(unsafe_code)]
- | ^^^^^^^^^^^ overruled by previous forbid
- |
- = note: our errors & omissions insurance policy doesn't cover unsafe Rust
-
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
- |
-LL | unsafe_code,
- | ----------- `forbid` level set here
-...
-LL | #[allow(unsafe_code)]
- | ^^^^^^^^^^^ overruled by previous forbid
- |
- = note: our errors & omissions insurance policy doesn't cover unsafe Rust
-
-error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
- --> $DIR/reasons-forbidden.rs:19:13
- |
-LL | unsafe_code,
- | ----------- `forbid` level set here
-...
-LL | #[allow(unsafe_code)]
- | ^^^^^^^^^^^ overruled by previous forbid
- |
- = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+ | ^^^^^^^^^^^
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0453`.