Skip to content

Commit 26ce027

Browse files
authored
Conditionally mark the test cfg as a well known cfg (#15007)
### What does this PR try to resolve? This PR conditionally mark the `test` cfg as a well known cfg depending on the target unit "test" field (ie `lib.test = false`, `[[bin]] test = false` and others). This is related to rust-lang/rust#117778 and https://users.rust-lang.org/t/cargo-what-is-the-purpose-of-lib-test-false/102361. When defining `lib.test = false` (and others), any use of `cfg(test)` will trigger the `unexpected_cfgs` lint. ```toml [lib] test = false # will now warn on cfg(test) ``` ### How should we test and review this PR? Best reviewed commit by commit. Second commit removes the `test` cfg from the `--check-cfg` args. ### Additional information T-compiler [MCP#785](rust-lang/compiler-team#785) and #14963 were of preparatory work. r? @epage
2 parents 730d997 + b757af9 commit 26ce027

File tree

4 files changed

+222
-8
lines changed

4 files changed

+222
-8
lines changed

src/cargo/core/compiler/mod.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,17 +1391,26 @@ fn check_cfg_args(unit: &Unit) -> Vec<OsString> {
13911391
}
13921392
arg_feature.push("))");
13931393

1394-
// In addition to the package features, we also include the `test` cfg (since
1395-
// compiler-team#785, as to be able to someday apply yt conditionaly), as well
1396-
// the `docsrs` cfg from the docs.rs service.
1394+
// In addition to the package features, we also conditionaly include the `test` cfg
1395+
// based on the unit target "test" field (ie `lib.test = false`, `[[bin]] test = false` and
1396+
// others).
13971397
//
1398-
// We include `docsrs` here (in Cargo) instead of rustc, since there is a much closer
1398+
// We also include `docsrs` here (in Cargo) instead of rustc, since there is a much closer
13991399
// relationship between Cargo and docs.rs than rustc and docs.rs. In particular, all
14001400
// users of docs.rs use Cargo, but not all users of rustc (like Rust-for-Linux) use docs.rs.
1401+
let arg_extra = if unit.target.tested()
1402+
// Benchmarks default to `test = false` but most of them still use the test crate
1403+
// and the `#[test]` attribute, so for now always mark `test` as well known for them.
1404+
|| unit.target.is_bench()
1405+
{
1406+
OsString::from("cfg(docsrs,test)")
1407+
} else {
1408+
OsString::from("cfg(docsrs)")
1409+
};
14011410

14021411
vec![
14031412
OsString::from("--check-cfg"),
1404-
OsString::from("cfg(docsrs,test)"),
1413+
arg_extra,
14051414
OsString::from("--check-cfg"),
14061415
arg_feature,
14071416
]

src/doc/src/reference/cargo-targets.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,10 @@ the target name.
216216
### The `test` field
217217

218218
The `test` field indicates whether or not the target is tested by default by
219-
[`cargo test`]. The default is `true` for lib, bins, and tests.
219+
[`cargo test`], and whenever the target is expected to have tests. Warnings
220+
may be reported when tests are unexpected (i.e., `test = false`).
221+
222+
The default is `true` for lib, bins, and tests.
220223

221224
> **Note**: Examples are built by [`cargo test`] by default to ensure they
222225
> continue to compile, but they are not *tested* by default. Setting `test =

tests/testsuite/check_cfg.rs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,193 @@ fn well_known_names_values_doctest() {
317317
.run();
318318
}
319319

320+
#[cargo_test(nightly, reason = "warning currently only on nightly")]
321+
fn test_false_lib() {
322+
let p = project()
323+
.file(
324+
"Cargo.toml",
325+
r#"
326+
[package]
327+
name = "foo"
328+
version = "0.1.0"
329+
edition = "2018"
330+
331+
[lib]
332+
test = false
333+
"#,
334+
)
335+
.file("src/lib.rs", "#[cfg(test)] mod tests {}")
336+
.build();
337+
338+
p.cargo("check -v")
339+
.with_stderr_does_not_contain(x!("rustc" => "cfg" of "docsrs,test"))
340+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs"))
341+
.with_stderr_data(str![[r#"
342+
...
343+
[WARNING] unexpected `cfg` condition name: `test`
344+
...
345+
346+
[WARNING] `foo` (lib) generated 1 warning
347+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
348+
349+
"#]])
350+
.run();
351+
352+
p.cargo("clean").run();
353+
p.cargo("test -v")
354+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs"))
355+
.with_stderr_data(str![[r#"
356+
...
357+
[WARNING] unexpected `cfg` condition name: `test`
358+
...
359+
360+
[WARNING] `foo` (lib) generated 1 warning
361+
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
362+
[DOCTEST] foo
363+
[RUNNING] [..]
364+
365+
"#]])
366+
.run();
367+
368+
p.cargo("clean").run();
369+
p.cargo("test --lib -v")
370+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs"))
371+
.with_stderr_data(str![[r#"
372+
...
373+
[WARNING] unexpected `cfg` condition name: `test`
374+
--> src/lib.rs:1:7
375+
...
376+
377+
[WARNING] `foo` (lib test) generated 1 warning
378+
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
379+
[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`
380+
381+
"#]])
382+
.run();
383+
}
384+
385+
#[cargo_test(nightly, reason = "warning currently only on nightly")]
386+
fn test_false_bins() {
387+
let p = project()
388+
.file(
389+
"Cargo.toml",
390+
r#"
391+
[package]
392+
name = "foo"
393+
version = "0.1.0"
394+
edition = "2018"
395+
396+
[[bin]]
397+
name = "daemon"
398+
test = false
399+
path = "src/deamon.rs"
400+
"#,
401+
)
402+
.file("src/main.rs", "fn main() {}\n#[cfg(test)] mod tests {}")
403+
.file("src/deamon.rs", "fn main() {}\n#[cfg(test)] mod tests {}")
404+
.build();
405+
406+
p.cargo("check -v")
407+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) // for foo
408+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs")) // for deamon
409+
.with_stderr_data(str![[r#"
410+
...
411+
[WARNING] unexpected `cfg` condition name: `test`
412+
...
413+
414+
[WARNING] `foo` (bin "daemon") generated 1 warning
415+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
416+
417+
"#]])
418+
.run();
419+
}
420+
421+
#[cargo_test(nightly, reason = "warning currently only on nightly")]
422+
fn test_false_examples() {
423+
let p = project()
424+
.file(
425+
"Cargo.toml",
426+
r#"
427+
[package]
428+
name = "foo"
429+
version = "0.1.0"
430+
edition = "2018"
431+
432+
[lib]
433+
test = false
434+
435+
[[example]]
436+
name = "daemon"
437+
test = false
438+
path = "src/deamon.rs"
439+
"#,
440+
)
441+
.file("src/lib.rs", "#[cfg(test)] mod tests {}")
442+
.file("src/deamon.rs", "fn main() {}\n#[cfg(test)] mod tests {}")
443+
.build();
444+
445+
p.cargo("check --examples -v")
446+
.with_stderr_does_not_contain(x!("rustc" => "cfg" of "docsrs,test"))
447+
.with_stderr_contains(x!("rustc" => "cfg" of "docsrs"))
448+
.with_stderr_data(str![[r#"
449+
...
450+
[WARNING] unexpected `cfg` condition name: `test`
451+
...
452+
453+
[WARNING] `foo` (lib) generated 1 warning
454+
...
455+
[WARNING] unexpected `cfg` condition name: `test`
456+
...
457+
458+
[WARNING] `foo` (example "daemon") generated 1 warning
459+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
460+
461+
"#]])
462+
.run();
463+
}
464+
465+
#[cargo_test(
466+
nightly,
467+
reason = "bench is nightly & warning currently only on nightly"
468+
)]
469+
fn test_false_benches() {
470+
let p = project()
471+
.file(
472+
"Cargo.toml",
473+
r#"
474+
[package]
475+
name = "foo"
476+
version = "0.0.0"
477+
edition = "2018"
478+
479+
[[bench]]
480+
name = "ben1"
481+
test = false
482+
path = "benches/ben1.rs"
483+
"#,
484+
)
485+
.file("src/lib.rs", "")
486+
.file(
487+
"benches/ben1.rs",
488+
r#"
489+
#![feature(test)]
490+
extern crate test;
491+
#[bench] fn run1(_ben: &mut test::Bencher) { }
492+
"#,
493+
)
494+
.build();
495+
496+
// Benches always require the `test` cfg, there should be no warning.
497+
p.cargo("bench --bench ben1")
498+
.with_stderr_data(str![[r#"
499+
[COMPILING] foo v0.0.0 ([ROOT]/foo)
500+
[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s
501+
[RUNNING] benches/ben1.rs (target/release/deps/ben1-[HASH][EXE])
502+
503+
"#]])
504+
.run();
505+
}
506+
320507
#[cargo_test]
321508
fn features_doc() {
322509
let p = project()

tests/testsuite/test.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,7 +4191,19 @@ fn test_hint_workspace_virtual() {
41914191
.file("a/src/lib.rs", "#[test] fn t1() {}")
41924192
.file("b/Cargo.toml", &basic_manifest("b", "0.1.0"))
41934193
.file("b/src/lib.rs", "#[test] fn t1() {assert!(false)}")
4194-
.file("c/Cargo.toml", &basic_manifest("c", "0.1.0"))
4194+
.file(
4195+
"c/Cargo.toml",
4196+
r#"
4197+
[package]
4198+
name = "c"
4199+
version = "0.1.0"
4200+
edition = "2015"
4201+
4202+
[[example]]
4203+
name = "ex1"
4204+
test = true
4205+
"#,
4206+
)
41954207
.file(
41964208
"c/src/lib.rs",
41974209
r#"
@@ -4275,14 +4287,17 @@ fn test_hint_workspace_virtual() {
42754287
[ERROR] test failed, to rerun pass `-p c --bin c`
42764288
[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE])
42774289
[ERROR] test failed, to rerun pass `-p c --test t1`
4290+
[RUNNING] unittests examples/ex1.rs (target/debug/examples/ex1-[HASH][EXE])
4291+
[ERROR] test failed, to rerun pass `-p c --example ex1`
42784292
[DOCTEST] a
42794293
[DOCTEST] b
42804294
[DOCTEST] c
42814295
[ERROR] doctest failed, to rerun pass `-p c --doc`
4282-
[ERROR] 4 targets failed:
4296+
[ERROR] 5 targets failed:
42834297
`-p b --lib`
42844298
`-p c --bin c`
42854299
`-p c --test t1`
4300+
`-p c --example ex1`
42864301
`-p c --doc`
42874302
42884303
"#]])

0 commit comments

Comments
 (0)