Skip to content

Commit b91f02e

Browse files
committed
Add future-incompatibility warning against keyword-as-ident
1 parent d89669e commit b91f02e

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

crates/cargo-platform/src/cfg.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ enum Token<'a> {
3131
String(&'a str),
3232
}
3333

34+
/// The list of keywords.
35+
///
36+
/// We should consider all the keywords, but some are conditional on
37+
/// the edition so for now we just consider true/false.
38+
///
39+
/// <https://doc.rust-lang.org/reference/keywords.html>
40+
pub(crate) const KEYWORDS: &[&str; 2] = &["true", "false"];
41+
3442
#[derive(Clone)]
3543
struct Tokenizer<'a> {
3644
s: iter::Peekable<str::CharIndices<'a>>,

crates/cargo-platform/src/lib.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
//!
1212
//! [`Platform`]: enum.Platform.html
1313
14-
use std::fmt;
1514
use std::str::FromStr;
15+
use std::{fmt, path::Path};
1616

1717
mod cfg;
1818
mod error;
1919

20+
use cfg::KEYWORDS;
2021
pub use cfg::{Cfg, CfgExpr};
2122
pub use error::{ParseError, ParseErrorKind};
2223

@@ -104,6 +105,35 @@ impl Platform {
104105
check_cfg_expr(cfg, warnings);
105106
}
106107
}
108+
109+
pub fn check_cfg_keywords(&self, warnings: &mut Vec<String>, path: &Path) {
110+
fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>, path: &Path) {
111+
match *expr {
112+
CfgExpr::Not(ref e) => check_cfg_expr(e, warnings, path),
113+
CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {
114+
for e in e {
115+
check_cfg_expr(e, warnings, path);
116+
}
117+
}
118+
CfgExpr::Value(ref e) => match e {
119+
Cfg::Name(name) | Cfg::KeyPair(name, _) => {
120+
if KEYWORDS.contains(&name.as_str()) {
121+
warnings.push(format!(
122+
"[{}] future-incompatibility: `cfg({e})` is deprecated as `{name}` is a keyword \
123+
and not an identifier and should not have have been accepted in this position.\n \
124+
| this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!",
125+
path.display()
126+
));
127+
}
128+
}
129+
},
130+
}
131+
}
132+
133+
if let Platform::Cfg(cfg) = self {
134+
check_cfg_expr(cfg, warnings, path);
135+
}
136+
}
107137
}
108138

109139
impl serde::Serialize for Platform {

src/cargo/util/context/target.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::core::compiler::{BuildOutput, LinkArgTarget};
33
use crate::util::CargoResult;
44
use serde::Deserialize;
55
use std::collections::{BTreeMap, HashMap};
6-
use std::path::PathBuf;
6+
use std::path::{Path, PathBuf};
77
use std::rc::Rc;
88

99
/// Config definition of a `[target.'cfg(…)']` table.
@@ -53,6 +53,13 @@ pub(super) fn load_target_cfgs(
5353
let target: BTreeMap<String, TargetCfgConfig> = gctx.get("target")?;
5454
tracing::debug!("Got all targets {:#?}", target);
5555
for (key, cfg) in target {
56+
if let Ok(platform) = key.parse::<cargo_platform::Platform>() {
57+
let mut warnings = Vec::new();
58+
platform.check_cfg_keywords(&mut warnings, &Path::new(".cargo/config.toml"));
59+
for w in warnings {
60+
gctx.shell().warn(w)?;
61+
}
62+
}
5663
if key.starts_with("cfg(") {
5764
// Unfortunately this is not able to display the location of the
5865
// unused key. Using config::Value<toml::Value> doesn't work. One

src/cargo/util/toml/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,7 @@ pub fn to_real_manifest(
13261326
for (name, platform) in original_toml.target.iter().flatten() {
13271327
let platform_kind: Platform = name.parse()?;
13281328
platform_kind.check_cfg_attributes(warnings);
1329+
platform_kind.check_cfg_keywords(warnings, manifest_file);
13291330
let platform_kind = Some(platform_kind);
13301331
validate_dependencies(
13311332
platform.dependencies.as_ref(),

tests/testsuite/cfg.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,9 +550,14 @@ fn cfg_keywords() {
550550

551551
p.cargo("check")
552552
.with_stderr_data(str![[r#"
553+
[WARNING] [[ROOT]/foo/Cargo.toml] future-incompatibility: `cfg(true)` is deprecated as `true` is a keyword and not an identifier and should not have have been accepted in this position.
554+
| this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!
555+
[WARNING] [.cargo/config.toml] future-incompatibility: `cfg(false)` is deprecated as `false` is a keyword and not an identifier and should not have have been accepted in this position.
556+
| this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!
553557
[LOCKING] 1 package to latest compatible version
554558
[CHECKING] foo v0.1.0 ([ROOT]/foo)
555-
...
559+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
560+
556561
"#]])
557562
.run();
558563
}

0 commit comments

Comments
 (0)