diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 872a4d54460..7efe77ef91f 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -224,11 +224,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { let mut unstable_opts = false; let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?; args.extend(compiler::lto_args(&self, unit)); + args.extend(compiler::features_args(&self, unit)); - for feature in &unit.features { - args.push("--cfg".into()); - args.push(format!("feature=\"{}\"", feature).into()); - } let script_meta = self.find_build_script_metadata(unit); if let Some(meta) = script_meta { if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) { diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 750981c9528..14916f1e591 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -645,10 +645,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { paths::create_dir_all(&doc_dir)?; rustdoc.arg("-o").arg(&doc_dir); - - for feat in &unit.features { - rustdoc.arg("--cfg").arg(&format!("feature=\"{}\"", feat)); - } + rustdoc.args(&features_args(cx, unit)); add_error_format_and_color(cx, &mut rustdoc, unit); add_allow_features(cx, &mut rustdoc); @@ -791,28 +788,6 @@ fn add_allow_features(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder) { } } -/// Add all features as cfg -fn add_features(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, unit: &Unit) { - for feat in &unit.features { - cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat)); - } - - if cx.bcx.config.cli_unstable().check_cfg_features { - // This generate something like this: - // - values(feature) - // - values(feature, "foo", "bar") - let mut arg = String::from("values(feature"); - for (&feat, _) in unit.pkg.summary().features() { - arg.push_str(", \""); - arg.push_str(&feat); - arg.push_str("\""); - } - arg.push(')'); - - cmd.arg("-Zunstable-options").arg("--check-cfg").arg(&arg); - } -} - /// Add error-format flags to the command. /// /// Cargo always uses JSON output. This has several benefits, such as being @@ -1009,7 +984,7 @@ fn build_base_args( cmd.arg("--cfg").arg("test"); } - add_features(cx, cmd, unit); + cmd.args(&features_args(cx, unit)); let meta = cx.files().metadata(unit); cmd.arg("-C").arg(&format!("metadata={}", meta)); @@ -1083,6 +1058,35 @@ fn build_base_args( Ok(()) } +/// Features with --cfg and all features with --check-cfg +fn features_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec { + let mut args = Vec::with_capacity(unit.features.len() + 2); + + for feat in &unit.features { + args.push(OsString::from("--cfg")); + args.push(OsString::from(format!("feature=\"{}\"", feat))); + } + + if cx.bcx.config.cli_unstable().check_cfg_features { + // This generate something like this: + // - values(feature) + // - values(feature, "foo", "bar") + let mut arg = OsString::from("values(feature"); + for (&feat, _) in unit.pkg.summary().features() { + arg.push(", \""); + arg.push(&feat); + arg.push("\""); + } + arg.push(")"); + + args.push(OsString::from("-Zunstable-options")); + args.push(OsString::from("--check-cfg")); + args.push(arg); + } + + args +} + fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec { let mut result = Vec::new(); let mut push = |arg: &str| { diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 6de7da90100..aa439016f14 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1132,9 +1132,9 @@ cargo doc -Z unstable-options -Z rustdoc-scrape-examples=examples * RFC: [#3013](https://github.com/rust-lang/rfcs/pull/3013) The `-Z check-cfg-features` argument tells Cargo to pass all possible features of a package to -`rustc` unstable `--check-cfg` command line as `--check-cfg=values(feature, ...)`. This enables -compile time checking of feature values in `#[cfg]`, `cfg!` and `#[cfg_attr]`. Note than this -command line options will probably become the default when stabilizing. +`rustc` and `rustdoc` unstable `--check-cfg` command line as `--check-cfg=values(feature, ...)`. +This enables compile time checking of feature values in `#[cfg]`, `cfg!` and `#[cfg_attr]`. +Note than this command line options will probably become the default when stabilizing. For instance: ``` diff --git a/tests/testsuite/doc.rs b/tests/testsuite/doc.rs index 1e069c85f0b..917981d4949 100644 --- a/tests/testsuite/doc.rs +++ b/tests/testsuite/doc.rs @@ -2697,3 +2697,40 @@ fn doc_lib_false_dep() { assert!(p.build_dir().join("doc/foo").exists()); assert!(!p.build_dir().join("doc/bar").exists()); } + +#[cfg_attr(windows, ignore)] // weird normalization issue with windows and cargo-test-support +#[cargo_test] +fn doc_check_cfg_features() { + if !is_nightly() { + // --check-cfg is a nightly only rustdoc command line + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.1.0" + + [features] + default = ["f_a"] + f_a = [] + f_b = [] + "#, + ) + .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}") + .build(); + + p.cargo("doc -v -Z check-cfg-features") + .masquerade_as_nightly_cargo() + .with_stderr( + "\ +[DOCUMENTING] foo v0.1.0 [..] +[RUNNING] `rustdoc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..] +[FINISHED] [..] +", + ) + .run(); +} diff --git a/tests/testsuite/test.rs b/tests/testsuite/test.rs index b8cebb9cd13..cdb2a914304 100644 --- a/tests/testsuite/test.rs +++ b/tests/testsuite/test.rs @@ -4536,3 +4536,42 @@ fn check_cfg_features() { ) .run(); } + +#[cfg_attr(windows, ignore)] // weird normalization issue with windows and cargo-test-support +#[cargo_test] +fn check_cfg_features_doc() { + if !is_nightly() { + // --check-cfg is a nightly only rustc and rustdoc command line + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.1.0" + + [features] + default = ["f_a"] + f_a = [] + f_b = [] + "#, + ) + .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}") + .build(); + + p.cargo("test -v --doc -Z check-cfg-features") + .masquerade_as_nightly_cargo() + .with_stderr( + "\ +[COMPILING] foo v0.1.0 [..] +[RUNNING] `rustc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..] +[FINISHED] test [unoptimized + debuginfo] target(s) in [..] +[DOCTEST] foo +[RUNNING] `rustdoc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..] +", + ) + .run(); +}