Skip to content

Commit 5e7af46

Browse files
committed
Auto merge of #67885 - tobithiel:fix_group_lint_allow_override, r=Mark-Simulacrum
rustc_session: allow overriding lint level of individual lints from a group Fixes #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.
2 parents 116dff9 + 3fc9253 commit 5e7af46

File tree

5 files changed

+65
-14
lines changed

5 files changed

+65
-14
lines changed

src/doc/rustc/src/command-line-arguments.md

+8
Original file line numberDiff line numberDiff line change
@@ -215,21 +215,29 @@ This controls which [target](targets/index.md) to produce.
215215

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

218+
_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.
219+
218220
<a id="option-a-allow"></a>
219221
## `-A`: set lint allowed
220222

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

225+
_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.
226+
223227
<a id="option-d-deny"></a>
224228
## `-D`: set lint denied
225229

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

232+
_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.
233+
228234
<a id="option-f-forbid"></a>
229235
## `-F`: set lint forbidden
230236

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

239+
_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.
240+
233241
<a id="option-z-unstable"></a>
234242
## `-Z`: set unstable options
235243

src/doc/rustc/src/lints/levels.md

+12
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@ And of course, you can mix these four flags together:
164164
$ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
165165
```
166166
167+
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:
168+
169+
```bash
170+
$ rustc lib.rs --crate-type=lib -D unused-variables -A unused-variables
171+
```
172+
173+
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:
174+
175+
```bash
176+
$ rustc lib.rs --crate-type=lib -D unused -A unused-variables
177+
```
178+
167179
### Via an attribute
168180
169181
You can also modify the lint level with a crate-wide attribute:

src/librustc_session/config.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1006,19 +1006,26 @@ pub fn get_cmd_lint_options(
10061006
matches: &getopts::Matches,
10071007
error_format: ErrorOutputType,
10081008
) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
1009-
let mut lint_opts = vec![];
1009+
let mut lint_opts_with_position = vec![];
10101010
let mut describe_lints = false;
10111011

10121012
for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
1013-
for lint_name in matches.opt_strs(level.as_str()) {
1013+
for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
10141014
if lint_name == "help" {
10151015
describe_lints = true;
10161016
} else {
1017-
lint_opts.push((lint_name.replace("-", "_"), level));
1017+
lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level));
10181018
}
10191019
}
10201020
}
10211021

1022+
lint_opts_with_position.sort_by_key(|x| x.0);
1023+
let lint_opts = lint_opts_with_position
1024+
.iter()
1025+
.cloned()
1026+
.map(|(_, lint_name, level)| (lint_name, level))
1027+
.collect();
1028+
10221029
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
10231030
lint::Level::from_str(&cap)
10241031
.unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// aux-build:lint-group-plugin-test.rs
2+
// check-pass
3+
// compile-flags: -D unused -A unused-variables
4+
5+
fn main() {
6+
let x = 1;
7+
}

src/tools/compiletest/src/runtest.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -1478,11 +1478,7 @@ impl<'test> TestCx<'test> {
14781478
WillExecute::No => TargetLocation::ThisDirectory(self.output_base_dir()),
14791479
};
14801480

1481-
let mut rustc = self.make_compile_args(&self.testpaths.file, output_file, emit_metadata);
1482-
1483-
rustc.arg("-L").arg(&self.aux_output_dir_name());
1484-
1485-
match self.config.mode {
1481+
let allow_unused = match self.config.mode {
14861482
CompileFail | Ui => {
14871483
// compile-fail and ui tests tend to have tons of unused code as
14881484
// it's just testing various pieces of the compile, but we don't
@@ -1495,11 +1491,18 @@ impl<'test> TestCx<'test> {
14951491
// via command line flags.
14961492
&& local_pm != Some(PassMode::Run)
14971493
{
1498-
rustc.args(&["-A", "unused"]);
1494+
AllowUnused::Yes
1495+
} else {
1496+
AllowUnused::No
14991497
}
15001498
}
1501-
_ => {}
1502-
}
1499+
_ => AllowUnused::No,
1500+
};
1501+
1502+
let mut rustc =
1503+
self.make_compile_args(&self.testpaths.file, output_file, emit_metadata, allow_unused);
1504+
1505+
rustc.arg("-L").arg(&self.aux_output_dir_name());
15031506

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

17151719
let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
17161720
(true, None)
@@ -1819,6 +1823,7 @@ impl<'test> TestCx<'test> {
18191823
input_file: &Path,
18201824
output_file: TargetLocation,
18211825
emit_metadata: EmitMetadata,
1826+
allow_unused: AllowUnused,
18221827
) -> Command {
18231828
let is_rustdoc = self.is_rustdoc();
18241829
let mut rustc = if !is_rustdoc {
@@ -1953,6 +1958,10 @@ impl<'test> TestCx<'test> {
19531958
rustc.arg("-Ctarget-feature=-crt-static");
19541959
}
19551960

1961+
if let AllowUnused::Yes = allow_unused {
1962+
rustc.args(&["-A", "unused"]);
1963+
}
1964+
19561965
rustc.args(&self.props.compile_flags);
19571966

19581967
rustc
@@ -2136,7 +2145,8 @@ impl<'test> TestCx<'test> {
21362145

21372146
let output_file = TargetLocation::ThisDirectory(self.output_base_dir());
21382147
let input_file = &self.testpaths.file;
2139-
let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
2148+
let mut rustc =
2149+
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);
21402150
rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir");
21412151

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

21502160
let output_file = TargetLocation::ThisFile(output_path.clone());
21512161
let input_file = &self.testpaths.file;
2152-
let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
2162+
let mut rustc =
2163+
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);
21532164

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

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

3502+
enum AllowUnused {
3503+
Yes,
3504+
No,
3505+
}
3506+
34903507
impl<T> fmt::Debug for ExpectedLine<T>
34913508
where
34923509
T: AsRef<str> + fmt::Debug,

0 commit comments

Comments
 (0)