mirror of
https://github.com/rust-lang/cargo
synced 2024-08-28 11:50:23 +00:00
Auto merge of #10799 - Urgau:check-cfg-fix-config-deserialization, r=ehuss
Fix deserialization of check-cfg in config.toml When improving the check-cfg implementation in https://github.com/rust-lang/cargo/pull/10566 I changed the internal representation of `check_cfg` from multiple `bool` options to one `Option<(bool, bool, bool, bool)>` but I didn't realize until https://github.com/rust-lang/rust/issues/82450#issuecomment-1169836928 that the internal representation is actually somewhat public as it's used in the `[unstable]` in `.cargo/config.toml`. And because TOML cannot represent tuples there is no way to set it from the `[unstable]` section. This PR fix this oversight by using a custom deserializer method similar to what was already done for `build-std`.
This commit is contained in:
commit
42311063f0
|
@ -641,6 +641,7 @@ unstable_cli_options!(
|
|||
build_std_features: Option<Vec<String>> = ("Configure features enabled for the standard library itself when building the standard library"),
|
||||
config_include: bool = ("Enable the `include` key in config files"),
|
||||
credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"),
|
||||
#[serde(deserialize_with = "deserialize_check_cfg")]
|
||||
check_cfg: Option<(/*features:*/ bool, /*well_known_names:*/ bool, /*well_known_values:*/ bool, /*output:*/ bool)> = ("Specify scope of compile-time checking of `cfg` names/values"),
|
||||
doctest_in_workspace: bool = ("Compile doctests with paths relative to the workspace root"),
|
||||
doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"),
|
||||
|
@ -733,6 +734,47 @@ where
|
|||
))
|
||||
}
|
||||
|
||||
fn deserialize_check_cfg<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<(bool, bool, bool, bool)>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
use serde::de::Error;
|
||||
let crates = match <Option<Vec<String>>>::deserialize(deserializer)? {
|
||||
Some(list) => list,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
parse_check_cfg(crates.into_iter()).map_err(D::Error::custom)
|
||||
}
|
||||
|
||||
fn parse_check_cfg(
|
||||
it: impl Iterator<Item = impl AsRef<str>>,
|
||||
) -> CargoResult<Option<(bool, bool, bool, bool)>> {
|
||||
let mut features = false;
|
||||
let mut well_known_names = false;
|
||||
let mut well_known_values = false;
|
||||
let mut output = false;
|
||||
|
||||
for e in it {
|
||||
match e.as_ref() {
|
||||
"features" => features = true,
|
||||
"names" => well_known_names = true,
|
||||
"values" => well_known_values = true,
|
||||
"output" => output = true,
|
||||
_ => bail!("unstable check-cfg only takes `features`, `names`, `values` or `output` as valid inputs"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some((
|
||||
features,
|
||||
well_known_names,
|
||||
well_known_values,
|
||||
output,
|
||||
)))
|
||||
}
|
||||
|
||||
impl CliUnstable {
|
||||
pub fn parse(
|
||||
&mut self,
|
||||
|
@ -783,34 +825,6 @@ impl CliUnstable {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_check_cfg(value: Option<&str>) -> CargoResult<Option<(bool, bool, bool, bool)>> {
|
||||
if let Some(value) = value {
|
||||
let mut features = false;
|
||||
let mut well_known_names = false;
|
||||
let mut well_known_values = false;
|
||||
let mut output = false;
|
||||
|
||||
for e in value.split(',') {
|
||||
match e {
|
||||
"features" => features = true,
|
||||
"names" => well_known_names = true,
|
||||
"values" => well_known_values = true,
|
||||
"output" => output = true,
|
||||
_ => bail!("flag -Zcheck-cfg only takes `features`, `names`, `values` or `output` as valid inputs"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some((
|
||||
features,
|
||||
well_known_names,
|
||||
well_known_values,
|
||||
output,
|
||||
)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
// Asserts that there is no argument to the flag.
|
||||
fn parse_empty(key: &str, value: Option<&str>) -> CargoResult<bool> {
|
||||
if let Some(v) = value {
|
||||
|
@ -868,7 +882,9 @@ impl CliUnstable {
|
|||
"minimal-versions" => self.minimal_versions = parse_empty(k, v)?,
|
||||
"advanced-env" => self.advanced_env = parse_empty(k, v)?,
|
||||
"config-include" => self.config_include = parse_empty(k, v)?,
|
||||
"check-cfg" => self.check_cfg = parse_check_cfg(v)?,
|
||||
"check-cfg" => {
|
||||
self.check_cfg = v.map_or(Ok(None), |v| parse_check_cfg(v.split(',')))?
|
||||
}
|
||||
"dual-proc-macros" => self.dual_proc_macros = parse_empty(k, v)?,
|
||||
// can also be set in .cargo/config or with and ENV
|
||||
"mtime-on-use" => self.mtime_on_use = parse_empty(k, v)?,
|
||||
|
|
|
@ -629,3 +629,74 @@ fn build_script_test() {
|
|||
.masquerade_as_nightly_cargo()
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn config_valid() {
|
||||
if !is_nightly() {
|
||||
// --check-cfg is a nightly only rustc command line
|
||||
return;
|
||||
}
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
|
||||
[features]
|
||||
f_a = []
|
||||
f_b = []
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.file(
|
||||
".cargo/config.toml",
|
||||
r#"
|
||||
[unstable]
|
||||
check-cfg = ["features", "names", "values"]
|
||||
"#,
|
||||
)
|
||||
.build();
|
||||
|
||||
p.cargo("build -v -Zcheck-cfg=features,names,values")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.with_stderr_contains(x!("rustc" => "names"))
|
||||
.with_stderr_contains(x!("rustc" => "values"))
|
||||
.with_stderr_contains(x!("rustc" => "values" of "feature" with "f_a" "f_b"))
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn config_invalid() {
|
||||
if !is_nightly() {
|
||||
// --check-cfg is a nightly only rustc command line
|
||||
return;
|
||||
}
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.file(
|
||||
".cargo/config.toml",
|
||||
r#"
|
||||
[unstable]
|
||||
check-cfg = ["va"]
|
||||
"#,
|
||||
)
|
||||
.build();
|
||||
|
||||
p.cargo("build")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.with_stderr_contains("error: unstable check-cfg only takes `features`, `names`, `values` or `output` as valid inputs")
|
||||
.with_status(101)
|
||||
.run();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue