Skip to content

Commit 9a926d6

Browse files
authored
fix(compile): Stop on denying warnings without --keep-going (#16725)
### What does this PR try to resolve? This had been discussed a little bit on [zulip](https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/Environment.20variable.20for.20.5Blints.5D.20table.3F/near/553969201). This then came up in usability feedback from @Urgau with rust-lang/rust's x.py having adopted `build.warnings`. The output from all of the other build targets causes the warnings to disappear off the screen which doesn't happen with errors because the build ends immediately. So we're making warnings act more like errors. ### How to test and review this PR? This is a follow up to #16721
2 parents b87ae61 + 96c3129 commit 9a926d6

3 files changed

Lines changed: 87 additions & 24 deletions

File tree

src/cargo/core/compiler/job_queue/mod.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ struct DrainState<'gctx> {
211211
}
212212

213213
/// Count of warnings, used to print a summary after the job succeeds
214-
#[derive(Default)]
214+
#[derive(Default, Clone)]
215215
pub struct WarningCount {
216216
/// total number of warnings
217217
pub total: usize,
@@ -248,7 +248,7 @@ impl WarningCount {
248248

249249
/// Used to keep track of how many fixable warnings there are
250250
/// and if fixable warnings are allowed
251-
#[derive(Default)]
251+
#[derive(Default, Copy, Clone)]
252252
pub enum FixableWarnings {
253253
NotAllowed,
254254
#[default]
@@ -668,20 +668,40 @@ impl<'gctx> DrainState<'gctx> {
668668
Message::FixDiagnostic(msg) => {
669669
self.print.print(&msg)?;
670670
}
671-
Message::Finish(id, artifact, result) => {
671+
Message::Finish(id, artifact, mut result) => {
672672
let unit = match artifact {
673673
// If `id` has completely finished we remove it
674674
// from the `active` map ...
675675
Artifact::All => {
676676
trace!("end: {:?}", id);
677677
self.finished += 1;
678-
self.report_warning_count(
679-
build_runner,
680-
id,
681-
&build_runner.bcx.rustc().workspace_wrapper,
682-
warning_handling,
683-
);
684-
self.active.remove(&id).unwrap()
678+
let unit = self.active.remove(&id).unwrap();
679+
// An error could add an entry for a `Unit`
680+
// with 0 warnings but having fixable
681+
// warnings be disallowed
682+
let count = self
683+
.warning_count
684+
.get(&id)
685+
.filter(|count| 0 < count.total)
686+
.cloned();
687+
if let Some(count) = count {
688+
self.report_warning_count(
689+
build_runner,
690+
&unit,
691+
&count,
692+
&build_runner.bcx.rustc().workspace_wrapper,
693+
warning_handling,
694+
);
695+
let stop_on_warnings = warning_handling == WarningHandling::Deny
696+
&& 0 < count.lints
697+
&& !build_runner.bcx.build_config.keep_going;
698+
if stop_on_warnings {
699+
result = Err(anyhow::format_err!(
700+
"warnings are denied by `build.warnings` configuration"
701+
))
702+
}
703+
}
704+
unit
685705
}
686706
// ... otherwise if it hasn't finished we leave it
687707
// in there as we'll get another `Finish` later on.
@@ -1052,20 +1072,13 @@ impl<'gctx> DrainState<'gctx> {
10521072
fn report_warning_count(
10531073
&mut self,
10541074
runner: &mut BuildRunner<'_, '_>,
1055-
id: JobId,
1075+
unit: &Unit,
1076+
count: &WarningCount,
10561077
rustc_workspace_wrapper: &Option<PathBuf>,
10571078
warning_handling: WarningHandling,
10581079
) {
10591080
let gctx = runner.bcx.gctx;
1060-
let count = match self.warning_count.get(&id) {
1061-
// An error could add an entry for a `Unit`
1062-
// with 0 warnings but having fixable
1063-
// warnings be disallowed
1064-
Some(count) if count.total > 0 => count,
1065-
None | Some(_) => return,
1066-
};
10671081
runner.compilation.lint_warning_count += count.lints;
1068-
let unit = &self.active[&id];
10691082
let mut message = descriptive_pkg_name(&unit.pkg.name(), &unit.target, &unit.mode);
10701083
message.push_str(" generated ");
10711084
match count.total {

src/doc/src/reference/unstable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,7 @@ in the future.
18591859
Controls how Cargo handles warnings. Allowed values are:
18601860
* `warn`: warnings are emitted as warnings (default).
18611861
* `allow`: warnings are hidden.
1862-
* `deny`: if warnings are emitted, an error will be raised at the end of the operation and the process will exit with a failure exit code.
1862+
* `deny`: if warnings are emitted, an error will be raised at the end of the current crate and the process. Use `--keep-going` to see all warnings.
18631863

18641864
## feature unification
18651865

tests/testsuite/warning_override.rs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ fn rustc_caching_allow_first() {
5151
= [NOTE] `#[warn(unused_variables)]` [..]on by default
5252
5353
[ERROR] `foo` (bin "foo") generated 1 warning[..]
54-
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
5554
[ERROR] warnings are denied by `build.warnings` configuration
5655
5756
"#]])
@@ -78,7 +77,6 @@ fn rustc_caching_deny_first() {
7877
= [NOTE] `#[warn(unused_variables)]` [..]on by default
7978
8079
[ERROR] `foo` (bin "foo") generated 1 warning[..]
81-
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
8280
[ERROR] warnings are denied by `build.warnings` configuration
8381
8482
"#]])
@@ -115,7 +113,6 @@ fn config() {
115113
= [NOTE] `#[warn(unused_variables)]` [..]on by default
116114
117115
[ERROR] `foo` (bin "foo") generated 1 warning[..]
118-
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
119116
[ERROR] warnings are denied by `build.warnings` configuration
120117
121118
"#]])
@@ -195,7 +192,6 @@ fn clippy() {
195192
[WARNING] unused import: `std::io`
196193
...
197194
[ERROR] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)
198-
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
199195
[ERROR] warnings are denied by `build.warnings` configuration
200196
201197
"#]])
@@ -289,3 +285,57 @@ fn hard_warning_allow() {
289285
.with_status(0)
290286
.run();
291287
}
288+
289+
#[cargo_test]
290+
fn keep_going() {
291+
let p = project()
292+
.file(
293+
"Cargo.toml",
294+
&format!(
295+
r#"
296+
[package]
297+
name = "foo"
298+
version = "0.0.1"
299+
edition = "2021"
300+
"#
301+
),
302+
)
303+
.file("build.rs", "fn main() { let x = 3; }")
304+
.file("src/main.rs", "fn main() { let y = 4; }")
305+
.build();
306+
307+
p.cargo("check")
308+
.masquerade_as_nightly_cargo(&["warnings"])
309+
.arg("-Zwarnings")
310+
.arg("--config")
311+
.arg("build.warnings='deny'")
312+
.with_stderr_data(str![[r#"
313+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
314+
[WARNING] unused variable: `x`
315+
...
316+
[ERROR] `foo` (build script) generated 1 warning
317+
[ERROR] warnings are denied by `build.warnings` configuration
318+
319+
"#]])
320+
.with_status(101)
321+
.run();
322+
323+
p.cargo("check --keep-going")
324+
.masquerade_as_nightly_cargo(&["warnings"])
325+
.arg("-Zwarnings")
326+
.arg("--config")
327+
.arg("build.warnings='deny'")
328+
.with_stderr_data(str![[r#"
329+
[WARNING] unused variable: `x`
330+
...
331+
[ERROR] `foo` (build script) generated 1 warning
332+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
333+
...
334+
[ERROR] `foo` (bin "foo") generated 1 warning (run `cargo fix --bin "foo" -p foo` to apply 1 suggestion)
335+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
336+
[ERROR] warnings are denied by `build.warnings` configuration
337+
338+
"#]])
339+
.with_status(101)
340+
.run();
341+
}

0 commit comments

Comments
 (0)