Skip to content

Commit

Permalink
Auto merge of rust-lang#67885 - tobithiel:fix_group_lint_allow_overri…
Browse files Browse the repository at this point in the history
…de, r=Mark-Simulacrum

rustc_session: allow overriding lint level of individual lints from a group

Fixes rust-lang#58211 and fixes rust-lang/rust-clippy#4778 and fixes rust-lang/rust-clippy#4091

Instead of hard-coding the lint level preferences (from lowest to highest precedence: `lint::Allow -> lint::Warn -> lint::Deny -> lint::Forbid`), the position of the argument in the command line gets taken into account.

Examples:
1. Passing `-D unused -A unused-variables` denies everything in the lint group `unused` **except** `unused-variables` which is explicitly allowed.
1. Passing `-A unused-variables -D unused` denies everything in the lint group `unused` **including** `unused-variables` since the allow is specified before the deny (and therefore overridden by the deny).

This matches the behavior that is already being used when specifying `allow`/`deny` in the source code.
  • Loading branch information
bors committed Feb 16, 2020
2 parents 116dff9 + 3fc9253 commit 5e7af46
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 14 deletions.
8 changes: 8 additions & 0 deletions src/doc/rustc/src/command-line-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,21 +215,29 @@ This controls which [target](targets/index.md) to produce.

This flag will set which lints should be set to the [warn level](lints/levels.md#warn).

_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information.

<a id="option-a-allow"></a>
## `-A`: set lint allowed

This flag will set which lints should be set to the [allow level](lints/levels.md#allow).

_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information.

<a id="option-d-deny"></a>
## `-D`: set lint denied

This flag will set which lints should be set to the [deny level](lints/levels.md#deny).

_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information.

<a id="option-f-forbid"></a>
## `-F`: set lint forbidden

This flag will set which lints should be set to the [forbid level](lints/levels.md#forbid).

_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information.

<a id="option-z-unstable"></a>
## `-Z`: set unstable options

Expand Down
12 changes: 12 additions & 0 deletions src/doc/rustc/src/lints/levels.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ And of course, you can mix these four flags together:
$ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
```
The order of these command line arguments is taken into account. The following allows the `unused-variables` lint, because it is the last argument for that lint:
```bash
$ rustc lib.rs --crate-type=lib -D unused-variables -A unused-variables
```
You can make use of this behavior by overriding the level of one specific lint out of a group of lints. The following example denies all the lints in the `unused` group, but explicitly allows the `unused-variables` lint in that group:
```bash
$ rustc lib.rs --crate-type=lib -D unused -A unused-variables
```
### Via an attribute
You can also modify the lint level with a crate-wide attribute:
Expand Down
13 changes: 10 additions & 3 deletions src/librustc_session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,19 +1006,26 @@ pub fn get_cmd_lint_options(
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
let mut lint_opts = vec![];
let mut lint_opts_with_position = vec![];
let mut describe_lints = false;

for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
for lint_name in matches.opt_strs(level.as_str()) {
for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
if lint_name == "help" {
describe_lints = true;
} else {
lint_opts.push((lint_name.replace("-", "_"), level));
lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level));
}
}
}

lint_opts_with_position.sort_by_key(|x| x.0);
let lint_opts = lint_opts_with_position
.iter()
.cloned()
.map(|(_, lint_name, level)| (lint_name, level))
.collect();

let lint_cap = matches.opt_str("cap-lints").map(|cap| {
lint::Level::from_str(&cap)
.unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui-fulldeps/lint-group-denied-lint-allowed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// aux-build:lint-group-plugin-test.rs
// check-pass
// compile-flags: -D unused -A unused-variables

fn main() {
let x = 1;
}
39 changes: 28 additions & 11 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1478,11 +1478,7 @@ impl<'test> TestCx<'test> {
WillExecute::No => TargetLocation::ThisDirectory(self.output_base_dir()),
};

let mut rustc = self.make_compile_args(&self.testpaths.file, output_file, emit_metadata);

rustc.arg("-L").arg(&self.aux_output_dir_name());

match self.config.mode {
let allow_unused = match self.config.mode {
CompileFail | Ui => {
// compile-fail and ui tests tend to have tons of unused code as
// it's just testing various pieces of the compile, but we don't
Expand All @@ -1495,11 +1491,18 @@ impl<'test> TestCx<'test> {
// via command line flags.
&& local_pm != Some(PassMode::Run)
{
rustc.args(&["-A", "unused"]);
AllowUnused::Yes
} else {
AllowUnused::No
}
}
_ => {}
}
_ => AllowUnused::No,
};

let mut rustc =
self.make_compile_args(&self.testpaths.file, output_file, emit_metadata, allow_unused);

rustc.arg("-L").arg(&self.aux_output_dir_name());

self.compose_and_run_compiler(rustc, None)
}
Expand Down Expand Up @@ -1710,7 +1713,8 @@ impl<'test> TestCx<'test> {
// Create the directory for the stdout/stderr files.
create_dir_all(aux_cx.output_base_dir()).unwrap();
let input_file = &aux_testpaths.file;
let mut aux_rustc = aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No);
let mut aux_rustc =
aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No, AllowUnused::No);

let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
(true, None)
Expand Down Expand Up @@ -1819,6 +1823,7 @@ impl<'test> TestCx<'test> {
input_file: &Path,
output_file: TargetLocation,
emit_metadata: EmitMetadata,
allow_unused: AllowUnused,
) -> Command {
let is_rustdoc = self.is_rustdoc();
let mut rustc = if !is_rustdoc {
Expand Down Expand Up @@ -1953,6 +1958,10 @@ impl<'test> TestCx<'test> {
rustc.arg("-Ctarget-feature=-crt-static");
}

if let AllowUnused::Yes = allow_unused {
rustc.args(&["-A", "unused"]);
}

rustc.args(&self.props.compile_flags);

rustc
Expand Down Expand Up @@ -2136,7 +2145,8 @@ impl<'test> TestCx<'test> {

let output_file = TargetLocation::ThisDirectory(self.output_base_dir());
let input_file = &self.testpaths.file;
let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
let mut rustc =
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);
rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir");

self.compose_and_run_compiler(rustc, None)
Expand All @@ -2149,7 +2159,8 @@ impl<'test> TestCx<'test> {

let output_file = TargetLocation::ThisFile(output_path.clone());
let input_file = &self.testpaths.file;
let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
let mut rustc =
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);

rustc.arg("-L").arg(self.aux_output_dir_name());

Expand Down Expand Up @@ -3000,6 +3011,7 @@ impl<'test> TestCx<'test> {
&self.testpaths.file.with_extension(UI_FIXED),
TargetLocation::ThisFile(self.make_exe_name()),
emit_metadata,
AllowUnused::No,
);
rustc.arg("-L").arg(&self.aux_output_dir_name());
let res = self.compose_and_run_compiler(rustc, None);
Expand Down Expand Up @@ -3487,6 +3499,11 @@ enum ExpectedLine<T: AsRef<str>> {
Text(T),
}

enum AllowUnused {
Yes,
No,
}

impl<T> fmt::Debug for ExpectedLine<T>
where
T: AsRef<str> + fmt::Debug,
Expand Down

0 comments on commit 5e7af46

Please sign in to comment.