From 5fff1e0e76f689619defb9b497642691bd15dcc0 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 28 Jul 2025 17:05:42 +0100 Subject: [PATCH 1/2] Duplicates of unknown_feature test --- tests/testsuite/cargo_features.rs | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/testsuite/cargo_features.rs b/tests/testsuite/cargo_features.rs index ba649b3d49f..e1a04bd804f 100644 --- a/tests/testsuite/cargo_features.rs +++ b/tests/testsuite/cargo_features.rs @@ -179,6 +179,64 @@ Caused by: .run(); } +#[cargo_test] +fn wrong_kind_of_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["build-dir"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + unknown cargo feature `build-dir` + +"#]]) + .run(); +} + +#[cargo_test] +fn feature_syntax() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["bad_feature"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + unknown cargo feature `bad_feature` + +"#]]) + .run(); +} + #[cargo_test] fn stable_feature_warns() { let p = project() From 45b4faa04a2514d3a5d86d6d32d7d92807304c11 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 28 Jul 2025 17:05:42 +0100 Subject: [PATCH 2/2] More helpful error for invalid cargo-features = [] --- src/cargo/core/features.rs | 27 ++++++++++++++++++++++++++- tests/testsuite/cargo_features.rs | 13 ++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 5c13b1a6e41..354d9295e48 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -620,7 +620,32 @@ impl Features { ) -> CargoResult<()> { let nightly_features_allowed = self.nightly_features_allowed; let Some((slot, feature)) = self.status(feature_name) else { - bail!("unknown cargo feature `{}`", feature_name) + let mut msg = format!("unknown Cargo.toml feature `{feature_name}`\n\n"); + let mut append_see_docs = true; + + if feature_name.contains('_') { + let _ = writeln!(msg, "Feature names must use '-' instead of '_'."); + append_see_docs = false; + } else { + let underscore_name = feature_name.replace('-', "_"); + if CliUnstable::help() + .iter() + .any(|(option, _)| *option == underscore_name) + { + let _ = writeln!( + msg, + "This feature can be enabled via -Z{feature_name} or the `[unstable]` section in config.toml." + ); + } + } + + if append_see_docs { + let _ = writeln!( + msg, + "See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information." + ); + } + bail!(msg) }; if *slot { diff --git a/tests/testsuite/cargo_features.rs b/tests/testsuite/cargo_features.rs index e1a04bd804f..8357eed565b 100644 --- a/tests/testsuite/cargo_features.rs +++ b/tests/testsuite/cargo_features.rs @@ -173,7 +173,9 @@ fn unknown_feature() { [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: - unknown cargo feature `foo` + unknown Cargo.toml feature `foo` + + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information. "#]]) .run(); @@ -202,7 +204,10 @@ fn wrong_kind_of_feature() { [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: - unknown cargo feature `build-dir` + unknown Cargo.toml feature `build-dir` + + This feature can be enabled via -Zbuild-dir or the `[unstable]` section in config.toml. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information. "#]]) .run(); @@ -231,7 +236,9 @@ fn feature_syntax() { [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: - unknown cargo feature `bad_feature` + unknown Cargo.toml feature `bad_feature` + + Feature names must use '-' instead of '_'. "#]]) .run();