Rollup merge of #77534 - Mark-Simulacrum:issue-70819-disallow-override-forbid-in-same-scope, r=petrochenkov

Disallow overriding forbid in same scope

Rebased #73379.

Fixes #70819.
This commit is contained in:
Yuki Okushi 2020-10-06 16:26:04 +09:00 committed by GitHub
commit bc600c3905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 150 additions and 24 deletions

View File

@ -10,6 +10,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_hir::{intravisit, HirId};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::LevelSource;
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource};
use rustc_middle::ty::query::Providers;
@ -95,6 +96,44 @@ impl<'s> LintLevelsBuilder<'s> {
self.sets.list.push(LintSet::CommandLine { specs });
}
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
/// (e.g. if a forbid was already inserted on the same scope), then emits a
/// diagnostic with no change to `specs`.
fn insert_spec(
&mut self,
specs: &mut FxHashMap<LintId, LevelSource>,
id: LintId,
(level, src): LevelSource,
) {
if let Some((old_level, old_src)) = specs.get(&id) {
if old_level == &Level::Forbid && level != Level::Forbid {
let mut diag_builder = struct_span_err!(
self.sess,
src.span(),
E0453,
"{}({}) incompatible with previous forbid in same scope",
level.as_str(),
src.name(),
);
match *old_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();
return;
}
}
specs.insert(id, (level, src));
}
/// Pushes a list of AST lint attributes onto this context.
///
/// This function will return a `BuilderPush` object which should be passed
@ -109,7 +148,7 @@ impl<'s> LintLevelsBuilder<'s> {
/// `#[allow]`
///
/// Don't forget to call `pop`!
pub fn push(
pub(crate) fn push(
&mut self,
attrs: &[ast::Attribute],
store: &LintStore,
@ -221,7 +260,7 @@ impl<'s> LintLevelsBuilder<'s> {
let src = LintSource::Node(name, li.span(), reason);
for &id in ids {
self.check_gated_lint(id, attr.span);
specs.insert(id, (level, src));
self.insert_spec(&mut specs, id, (level, src));
}
}
@ -235,7 +274,7 @@ impl<'s> LintLevelsBuilder<'s> {
reason,
);
for id in ids {
specs.insert(*id, (level, src));
self.insert_spec(&mut specs, *id, (level, src));
}
}
Err((Some(ids), new_lint_name)) => {
@ -272,7 +311,7 @@ impl<'s> LintLevelsBuilder<'s> {
reason,
);
for id in ids {
specs.insert(*id, (level, src));
self.insert_spec(&mut specs, *id, (level, src));
}
}
Err((None, _)) => {

View File

@ -9,7 +9,7 @@ use rustc_session::lint::{builtin, Level, Lint, LintId};
use rustc_session::{DiagnosticMessageId, Session};
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
use rustc_span::{Span, Symbol};
use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
@ -25,6 +25,24 @@ pub enum LintSource {
CommandLine(Symbol),
}
impl LintSource {
pub fn name(&self) -> Symbol {
match *self {
LintSource::Default => symbol::kw::Default,
LintSource::Node(name, _, _) => name,
LintSource::CommandLine(name) => name,
}
}
pub fn span(&self) -> Span {
match *self {
LintSource::Default => DUMMY_SP,
LintSource::Node(_, span, _) => span,
LintSource::CommandLine(_) => DUMMY_SP,
}
}
}
pub type LevelSource = (Level, LintSource);
pub struct LintLevelSets {

View File

@ -0,0 +1,49 @@
// This test is checking that you cannot override a `forbid` by adding in other
// attributes later in the same scope. (We already ensure that you cannot
// override it in nested scopes).
// 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 curretly that happens two or three different times, depending on
// compiler flags.
//
// I decided avoiding the redundant output was not worth the time in engineering
// effort for bug like this, which 1. end users are unlikely to run into in the
// first place, and 2. they won't see the redundant output anyway.
// compile-flags: -Z deduplicate-diagnostics=yes
fn forbid_first(num: i32) -> i32 {
#![forbid(unused)]
#![deny(unused)]
//~^ ERROR: deny(unused) incompatible with previous forbid in same scope [E0453]
#![warn(unused)]
//~^ ERROR: warn(unused) incompatible with previous forbid in same scope [E0453]
#![allow(unused)]
//~^ ERROR: allow(unused) incompatible with previous forbid in same scope [E0453]
num * num
}
fn forbid_last(num: i32) -> i32 {
#![deny(unused)]
#![warn(unused)]
#![allow(unused)]
#![forbid(unused)]
num * num
}
fn forbid_multiple(num: i32) -> i32 {
#![forbid(unused)]
#![forbid(unused)]
num * num
}
fn main() {
forbid_first(10);
forbid_last(10);
forbid_multiple(10);
}

View File

@ -0,0 +1,29 @@
error[E0453]: deny(unused) incompatible with previous forbid in same scope
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:19:13
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
LL | #![deny(unused)]
| ^^^^^^
error[E0453]: warn(unused) incompatible with previous forbid in same scope
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
...
LL | #![warn(unused)]
| ^^^^^^
error[E0453]: allow(unused) incompatible with previous forbid in same scope
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:23:14
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
...
LL | #![allow(unused)]
| ^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0453`.

View File

@ -8,8 +8,8 @@ extern "C" {
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] ...
#[forbid(unused_mut)] d: i32,
#[deny(unused_mut)] #[warn(unused_mut)] ...
);
}
@ -17,16 +17,16 @@ type FnType = fn(
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] e: i32
#[forbid(unused_mut)] d: i32,
#[deny(unused_mut)] #[warn(unused_mut)] e: i32
);
pub fn foo(
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] _e: i32
#[forbid(unused_mut)] d: i32,
#[deny(unused_mut)] #[warn(unused_mut)] _e: i32
) {}
// self

View File

@ -3,7 +3,6 @@
// Test that the whole restriction group is not enabled
#![warn(clippy::restriction)]
#![deny(clippy::restriction)]
#![forbid(clippy::restriction)]
#![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)]
#[inline(always)]

View File

@ -1,5 +1,5 @@
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
--> $DIR/attrs.rs:9:1
--> $DIR/attrs.rs:8:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
@ -7,7 +7,7 @@ LL | #[inline(always)]
= note: `-D clippy::inline-always` implied by `-D warnings`
error: the since field must contain a semver-compliant version
--> $DIR/attrs.rs:29:14
--> $DIR/attrs.rs:28:14
|
LL | #[deprecated(since = "forever")]
| ^^^^^^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | #[deprecated(since = "forever")]
= note: `-D clippy::deprecated-semver` implied by `-D warnings`
error: the since field must contain a semver-compliant version
--> $DIR/attrs.rs:32:14
--> $DIR/attrs.rs:31:14
|
LL | #[deprecated(since = "1")]
| ^^^^^^^^^^^
@ -37,13 +37,5 @@ LL | #![deny(clippy::restriction)]
|
= help: try enabling only the lints you really need
error: restriction lints are not meant to be all enabled
--> $DIR/attrs.rs:6:11
|
LL | #![forbid(clippy::restriction)]
| ^^^^^^^^^^^^^^^^^^^
|
= help: try enabling only the lints you really need
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors