diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index dfe60d5e73e..33dfd48661f 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -158,6 +158,29 @@ macro_rules! get_value_typed { }; } +pub const TOP_LEVEL_CONFIG_KEYS: &[&str] = &[ + "paths", + "alias", + "build", + "credential-alias", + "doc", + "env", + "future-incompat-report", + "cache", + "cargo-new", + "http", + "install", + "net", + "patch", + "profile", + "resolver", + "registries", + "registry", + "source", + "target", + "term", +]; + /// Indicates why a config value is being loaded. #[derive(Clone, Copy, Debug)] enum WhyLoad { diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index fd81b5ae0ca..2777b3fdd7b 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -35,6 +35,7 @@ use crate::util::interning::InternedString; use crate::util::lints::{get_key_value_span, rel_cwd_manifest_path}; use crate::util::{ self, GlobalContext, IntoUrl, OnceExt, OptVersionReq, context::ConfigRelativePath, + context::TOP_LEVEL_CONFIG_KEYS, }; mod embedded; @@ -2887,11 +2888,18 @@ fn deprecated_underscore( } fn warn_on_unused(unused: &BTreeSet, warnings: &mut Vec) { + use std::fmt::Write as _; + for key in unused { - warnings.push(format!("unused manifest key: {}", key)); - if key == "profiles.debug" { - warnings.push("use `[profile.dev]` to configure debug builds".to_string()); + let mut message = format!("unused manifest key: {}", key); + if TOP_LEVEL_CONFIG_KEYS.iter().any(|c| c == key) { + write!( + &mut message, + "\nhelp: {key} is a valid .cargo/config.toml key" + ) + .unwrap(); } + warnings.push(message); } } diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs index 8bd1b0c4e20..ca90a7eaa9a 100644 --- a/tests/testsuite/bad_config.rs +++ b/tests/testsuite/bad_config.rs @@ -772,74 +772,125 @@ fn unused_keys() { .file( "Cargo.toml", r#" - [package] - name = "foo" - version = "0.1.0" - edition = "2015" - authors = [] +paths = ["/path/to/override"] - [target.foo] - bar = "3" - "#, - ) - .file("src/lib.rs", "") - .build(); +[package] +name = "foo" +version = "0.1.0" +edition = "2015" +authors = [] +unused = "foo" - p.cargo("check") - .with_stderr_data(str![[r#" -[WARNING] unused manifest key: target.foo.bar -[CHECKING] foo v0.1.0 ([ROOT]/foo) -[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[target.foo] +bar = "3" -"#]]) - .run(); +[lib] +build = "foo" - let p = project() - .file( - "Cargo.toml", - r#" - [package] +## Config fields - name = "foo" - version = "0.5.0" - edition = "2015" - authors = ["wycats@example.com"] - unused = "foo" - "#, - ) - .file("src/lib.rs", "pub fn foo() {}") - .build(); - p.cargo("check") - .with_stderr_data(str![[r#" -[WARNING] unused manifest key: package.unused -[CHECKING] foo v0.5.0 ([ROOT]/foo) -[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[alias] +b = "build" -"#]]) - .run(); +[build] +jobs = 1 - let p = project() - .at("bar") - .file( - "Cargo.toml", - r#" - [package] +[credential-alias] +my-alias = ["/usr/bin/cargo-credential-example", "--argument", "value", "--flag"] - name = "foo" - version = "0.5.0" - edition = "2015" - authors = ["wycats@example.com"] +[doc] +browser = "chromium" - [lib] - build = "foo" - "#, +[env] +ENV_VAR_NAME = "value" + +[future-incompat-report] +frequency = 'always' + +[cache] +auto-clean-frequency = "1 day" + +[cargo-new] +vcs = "none" + +[http] +debug = false + +[install] +root = "/some/path" + +[net] +retry = 3 + +[net.ssh] +known-hosts = ["..."] + +[resolver] +incompatible-rust-versions = "allow" + +[registries.alternative] +index = "…" + +[registries.crates-io] +protocol = "sparse" + +[registry] +default = "…" + +[source.alternative] +replace-with = "…" + +[target.'cfg(unix)'] +linker = "…" + +[term] +quiet = false +"#, ) - .file("src/lib.rs", "pub fn foo() {}") + .file("src/lib.rs", "") .build(); + p.cargo("check") .with_stderr_data(str![[r#" +[WARNING] unused manifest key: alias +[HELP] alias is a valid .cargo/config.toml key +[WARNING] unused manifest key: build +[HELP] build is a valid .cargo/config.toml key +[WARNING] unused manifest key: cache +[HELP] cache is a valid .cargo/config.toml key +[WARNING] unused manifest key: cargo-new +[HELP] cargo-new is a valid .cargo/config.toml key +[WARNING] unused manifest key: credential-alias +[HELP] credential-alias is a valid .cargo/config.toml key +[WARNING] unused manifest key: doc +[HELP] doc is a valid .cargo/config.toml key +[WARNING] unused manifest key: env +[HELP] env is a valid .cargo/config.toml key +[WARNING] unused manifest key: future-incompat-report +[HELP] future-incompat-report is a valid .cargo/config.toml key +[WARNING] unused manifest key: http +[HELP] http is a valid .cargo/config.toml key +[WARNING] unused manifest key: install +[HELP] install is a valid .cargo/config.toml key [WARNING] unused manifest key: lib.build -[CHECKING] foo v0.5.0 ([ROOT]/bar) +[WARNING] unused manifest key: net +[HELP] net is a valid .cargo/config.toml key +[WARNING] unused manifest key: package.unused +[WARNING] unused manifest key: paths +[HELP] paths is a valid .cargo/config.toml key +[WARNING] unused manifest key: registries +[HELP] registries is a valid .cargo/config.toml key +[WARNING] unused manifest key: registry +[HELP] registry is a valid .cargo/config.toml key +[WARNING] unused manifest key: resolver +[HELP] resolver is a valid .cargo/config.toml key +[WARNING] unused manifest key: source +[HELP] source is a valid .cargo/config.toml key +[WARNING] unused manifest key: target.cfg(unix).linker +[WARNING] unused manifest key: target.foo.bar +[WARNING] unused manifest key: term +[HELP] term is a valid .cargo/config.toml key +[CHECKING] foo v0.1.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]])