diff --git a/Cargo.lock b/Cargo.lock index fcf6464d21f..207a93af0ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -318,7 +318,7 @@ dependencies = [ "cargo-credential-libsecret", "cargo-credential-macos-keychain", "cargo-credential-wincred", - "cargo-platform 0.2.0", + "cargo-platform 0.3.0", "cargo-test-support", "cargo-util", "cargo-util-schemas", @@ -445,7 +445,7 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.2.0" +version = "0.3.0" dependencies = [ "serde", ] @@ -3053,7 +3053,7 @@ name = "resolver-tests" version = "0.0.0" dependencies = [ "cargo", - "cargo-platform 0.2.0", + "cargo-platform 0.3.0", "cargo-util", "cargo-util-schemas", "proptest", diff --git a/Cargo.toml b/Cargo.toml index c44b9a17125..2ee74ed0ec3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ cargo-credential = { version = "0.4.2", path = "credential/cargo-credential" } cargo-credential-libsecret = { version = "0.4.12", path = "credential/cargo-credential-libsecret" } cargo-credential-macos-keychain = { version = "0.4.12", path = "credential/cargo-credential-macos-keychain" } cargo-credential-wincred = { version = "0.4.12", path = "credential/cargo-credential-wincred" } -cargo-platform = { path = "crates/cargo-platform", version = "0.2.0" } +cargo-platform = { path = "crates/cargo-platform", version = "0.3.0" } cargo-test-macro = { version = "0.4.1", path = "crates/cargo-test-macro" } cargo-test-support = { version = "0.7.1", path = "crates/cargo-test-support" } cargo-util = { version = "0.2.19", path = "crates/cargo-util" } diff --git a/crates/cargo-platform/Cargo.toml b/crates/cargo-platform/Cargo.toml index 778a7cf6742..baa75741232 100644 --- a/crates/cargo-platform/Cargo.toml +++ b/crates/cargo-platform/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-platform" -version = "0.2.0" +version = "0.3.0" edition.workspace = true license.workspace = true rust-version.workspace = true diff --git a/crates/cargo-platform/src/cfg.rs b/crates/cargo-platform/src/cfg.rs index 79aaa02c23f..5928e4c2d6c 100644 --- a/crates/cargo-platform/src/cfg.rs +++ b/crates/cargo-platform/src/cfg.rs @@ -11,6 +11,8 @@ pub enum CfgExpr { All(Vec), Any(Vec), Value(Cfg), + True, + False, } /// A cfg value. @@ -147,6 +149,8 @@ impl CfgExpr { CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)), CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)), CfgExpr::Value(ref e) => cfg.contains(e), + CfgExpr::True => true, + CfgExpr::False => false, } } } @@ -174,6 +178,8 @@ impl fmt::Display for CfgExpr { CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)), CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)), CfgExpr::Value(ref e) => write!(f, "{}", e), + CfgExpr::True => write!(f, "true"), + CfgExpr::False => write!(f, "false"), } } } @@ -229,7 +235,11 @@ impl<'a> Parser<'a> { self.eat(&Token::RightParen)?; Ok(CfgExpr::Not(Box::new(e))) } - Some(Ok(..)) => self.cfg().map(CfgExpr::Value), + Some(Ok(..)) => self.cfg().map(|v| match v { + Cfg::Name(n) if n == "true" => CfgExpr::True, + Cfg::Name(n) if n == "false" => CfgExpr::False, + v => CfgExpr::Value(v), + }), Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()), None => Err(ParseError::new( self.t.orig, diff --git a/crates/cargo-platform/src/lib.rs b/crates/cargo-platform/src/lib.rs index f91b61708bb..96b2485775a 100644 --- a/crates/cargo-platform/src/lib.rs +++ b/crates/cargo-platform/src/lib.rs @@ -98,6 +98,7 @@ impl Platform { )) }, } + CfgExpr::True | CfgExpr::False => {}, } } @@ -115,30 +116,18 @@ impl Platform { check_cfg_expr(e, warnings, path); } } + CfgExpr::True | CfgExpr::False => {} CfgExpr::Value(ref e) => match e { Cfg::Name(name) | Cfg::KeyPair(name, _) => { if !name.raw && KEYWORDS.contains(&name.as_str()) { - if name.as_str() == "true" || name.as_str() == "false" { - warnings.push(format!( - "[{}] future-incompatibility: the meaning of `cfg({e})` will change in the future\n \ - | Cargo is erroneously allowing `cfg(true)` and `cfg(false)`, but both forms are interpreted as false unless manually overridden with `--cfg`.\n \ - | In the future these will be built-in defines that will have the corresponding true/false value.\n \ - | It is recommended to avoid using these configs until they are properly supported.\n \ - | See for more information.\n \ - |\n \ - | help: use raw-idents instead: `cfg(r#{name})`", - path.display() - )); - } else { - warnings.push(format!( - "[{}] future-incompatibility: `cfg({e})` is deprecated as `{name}` is a keyword \ - and not an identifier and should not have have been accepted in this position.\n \ - | this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!\n \ - |\n \ - | help: use raw-idents instead: `cfg(r#{name})`", - path.display() - )); - } + warnings.push(format!( + "[{}] future-incompatibility: `cfg({e})` is deprecated as `{name}` is a keyword \ + and not an identifier and should not have have been accepted in this position.\n \ + | this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!\n \ + |\n \ + | help: use raw-idents instead: `cfg(r#{name})`", + path.display() + )); } } }, diff --git a/crates/cargo-platform/tests/test_cfg.rs b/crates/cargo-platform/tests/test_cfg.rs index 0fdf307fab7..59cb27d54f4 100644 --- a/crates/cargo-platform/tests/test_cfg.rs +++ b/crates/cargo-platform/tests/test_cfg.rs @@ -39,6 +39,8 @@ macro_rules! e { (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*])); (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*])); (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*)))); + (true) => (CfgExpr::True); + (false) => (CfgExpr::False); (($($t:tt)*)) => (e!($($t)*)); ($($t:tt)*) => (CfgExpr::Value(c!($($t)*))); } @@ -122,6 +124,9 @@ fn cfg_expr() { good(" foo=\"3\" ", e!(foo = "3")); good("foo = \"3 e\"", e!(foo = "3 e")); + good("true", e!(true)); + good("false", e!(false)); + good("all()", e!(all())); good("all(a)", e!(all(a))); good("all(a, b)", e!(all(a, b))); @@ -249,6 +254,8 @@ fn check_cfg_attributes() { ok("windows"); ok("any(not(unix), windows)"); ok("foo"); + ok("true"); + ok("false"); ok("target_arch = \"abc\""); ok("target_feature = \"abc\""); diff --git a/tests/testsuite/cfg.rs b/tests/testsuite/cfg.rs index 9b5cd240765..cac36f92621 100644 --- a/tests/testsuite/cfg.rs +++ b/tests/testsuite/cfg.rs @@ -545,6 +545,7 @@ fn cfg_raw_idents() { p.cargo("check") .with_stderr_data(str![[r#" [LOCKING] 1 package to latest compatible version +[CHECKING] b v0.0.1 ([ROOT]/foo/b) [CHECKING] foo v0.1.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s @@ -638,24 +639,182 @@ fn cfg_keywords() { p.cargo("check") .with_stderr_data(str![[r#" -[WARNING] [[ROOT]/foo/Cargo.toml] future-incompatibility: the meaning of `cfg(true)` will change in the future - | Cargo is erroneously allowing `cfg(true)` and `cfg(false)`, but both forms are interpreted as false unless manually overridden with `--cfg`. - | In the future these will be built-in defines that will have the corresponding true/false value. - | It is recommended to avoid using these configs until they are properly supported. - | See for more information. - | - | [HELP] use raw-idents instead: `cfg(r#true)` -[WARNING] [.cargo/config.toml] future-incompatibility: the meaning of `cfg(false)` will change in the future - | Cargo is erroneously allowing `cfg(true)` and `cfg(false)`, but both forms are interpreted as false unless manually overridden with `--cfg`. - | In the future these will be built-in defines that will have the corresponding true/false value. - | It is recommended to avoid using these configs until they are properly supported. - | See for more information. - | - | [HELP] use raw-idents instead: `cfg(r#false)` [LOCKING] 1 package to latest compatible version +[CHECKING] b v0.0.1 ([ROOT]/foo/b) [CHECKING] foo v0.1.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } + +#[cargo_test] +fn cfg_booleans() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(true)'.dependencies] + b = { path = 'b' } + + [target.'cfg(false)'.dependencies] + c = { path = 'c' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "0.0.1")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["cfg-boolean-literals feature"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_booleans_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [target.'cfg(true)'] + rustflags = [] + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_booleans_not() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(not(false))'.dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_booleans_combinators() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(all(any(true), not(false), true))'.dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_booleans_rustflags_no_effect() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(true)'.dependencies] + b = { path = 'b' } + + [target.'cfg(false)'.dependencies] + c = { path = 'c' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "0.0.1")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .env("RUSTFLAGS", "--cfg false") + .run(); +}