about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-20 20:14:09 +0000
committerbors <bors@rust-lang.org>2024-05-20 20:14:09 +0000
commitb92758a9aef1cef7b79e2b72c3d8ba113e547f89 (patch)
tree9734f7e60c99909b42378de46e49a0644c1695b9
parentbe71fd477243f253a735bb35e0cd23cc528cf30a (diff)
parentccd3e99a1a7acdbb3819c0d607fa93c35985c377 (diff)
downloadrust-b92758a9aef1cef7b79e2b72c3d8ba113e547f89.tar.gz
rust-b92758a9aef1cef7b79e2b72c3d8ba113e547f89.zip
Auto merge of #125219 - Urgau:check-cfg-cargo-config, r=fmease
Update `unexpected_cfgs` lint for Cargo new `check-cfg` config

This PR updates the diagnostics output of the `unexpected_cfgs` lint for Cargo new `check-cfg` config.

It's a simple and cost-less alternative to the build-script `cargo::rustc-check-cfg` instruction.

```toml
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(foo, values("bar"))'] }
```

This PR also adds a Cargo specific section regarding check-cfg and Cargo inside rustc's book (motivation is described inside the file, but mainly check-cfg is a rustc feature not a Cargo one, Cargo only enabled the feature, it does not own it; T-cargo even considers the `check-cfg` lint config to be an implementation detail).

This PR also updates the links to refer to that sub-page when using Cargo from rustc.

As well as updating the lint doc to refer to the check-cfg docs.

~**Not to be merged before https://github.com/rust-lang/cargo/pull/13913 reaches master!**~ (EDIT: merged in https://github.com/rust-lang/rust/pull/125237)

`@rustbot` label +F-check-cfg
r? `@fmease` *(feel free to roll)*
Fixes https://github.com/rust-lang/rust/issues/124800
cc `@epage` `@weihanglo`
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs50
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs11
-rw-r--r--src/doc/rustc/src/SUMMARY.md3
-rw-r--r--src/doc/rustc/src/check-cfg/cargo-specifics.md73
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr20
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr20
-rw-r--r--tests/ui/check-cfg/diagnotics.cargo.stderr60
-rw-r--r--tests/ui/check-cfg/diagnotics.rs5
-rw-r--r--tests/ui/check-cfg/diagnotics.rustc.stderr26
9 files changed, 210 insertions, 58 deletions
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index 3c423b4e2aa..3fa04ab75f8 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -41,6 +41,24 @@ fn check_cfg_expected_note(
     note
 }
 
+enum EscapeQuotes {
+    Yes,
+    No,
+}
+
+fn to_check_cfg_arg(name: Symbol, value: Option<Symbol>, quotes: EscapeQuotes) -> String {
+    if let Some(value) = value {
+        let value = str::escape_debug(value.as_str()).to_string();
+        let values = match quotes {
+            EscapeQuotes::Yes => format!("\\\"{}\\\"", value.replace("\"", "\\\\\\\\\"")),
+            EscapeQuotes::No => format!("\"{value}\""),
+        };
+        format!("cfg({name}, values({values}))")
+    } else {
+        format!("cfg({name})")
+    }
+}
+
 pub(super) fn unexpected_cfg_name(
     sess: &Session,
     diag: &mut Diag<'_, ()>,
@@ -155,20 +173,18 @@ pub(super) fn unexpected_cfg_name(
         }
     }
 
-    let inst = if let Some((value, _value_span)) = value {
-        let pre = if is_from_cargo { "\\" } else { "" };
-        format!("cfg({name}, values({pre}\"{value}{pre}\"))")
-    } else {
-        format!("cfg({name})")
-    };
+    let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
 
     if is_from_cargo {
         if !is_feature_cfg {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead"));
+            diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No)));
+            diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes)));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration");
     } else {
-        diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
+        let inst = inst(EscapeQuotes::No);
+        diag.help(format!("to expect this configuration use `--check-cfg={inst}`",));
         diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
     }
 }
@@ -251,12 +267,7 @@ pub(super) fn unexpected_cfg_value(
     // do it if they want, but should not encourage them.
     let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name);
 
-    let inst = if let Some((value, _value_span)) = value {
-        let pre = if is_from_cargo { "\\" } else { "" };
-        format!("cfg({name}, values({pre}\"{value}{pre}\"))")
-    } else {
-        format!("cfg({name})")
-    };
+    let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
 
     if is_from_cargo {
         if name == sym::feature {
@@ -266,12 +277,15 @@ pub(super) fn unexpected_cfg_value(
                 diag.help("consider defining some features in `Cargo.toml`");
             }
         } else if !is_cfg_a_well_know_name {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead"));
+            diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No)));
+            diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes)));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration");
     } else {
         if !is_cfg_a_well_know_name {
-            diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
+            let inst = inst(EscapeQuotes::No);
+            diag.help(format!("to expect this configuration use `--check-cfg={inst}`",));
         }
         diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
     }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 3b8bec887ea..82f16b31a66 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3339,11 +3339,14 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// This lint is only active when `--check-cfg` arguments are being passed
-    /// to the compiler and triggers whenever an unexpected condition name or value is used.
+    /// This lint is only active when [`--check-cfg`][check-cfg] arguments are being
+    /// passed to the compiler and triggers whenever an unexpected condition name or value is
+    /// used.
+    ///
+    /// See the [Checking Conditional Configurations][check-cfg] section for more
+    /// details.
     ///
-    /// The known condition include names or values passed in `--check-cfg`, and some
-    /// well-knows names and values built into the compiler.
+    /// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
     pub UNEXPECTED_CFGS,
     Warn,
     "detects unexpected names and values in `#[cfg]` conditions",
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index c7e3293e35a..cfe4dfeb59c 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -84,7 +84,8 @@
 - [Profile-guided Optimization](profile-guided-optimization.md)
 - [Instrumentation-based Code Coverage](instrument-coverage.md)
 - [Linker-plugin-based LTO](linker-plugin-lto.md)
-- [Checking conditional configurations](check-cfg.md)
+- [Checking Conditional Configurations](check-cfg.md)
+    - [Cargo Specifics](check-cfg/cargo-specifics.md)
 - [Exploit Mitigations](exploit-mitigations.md)
 - [Symbol Mangling](symbol-mangling/index.md)
     - [v0 Symbol Format](symbol-mangling/v0.md)
diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md
new file mode 100644
index 00000000000..bfa60161926
--- /dev/null
+++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md
@@ -0,0 +1,73 @@
+# Cargo Specifics - Checking Conditional Configurations
+
+<!--
+This page is currently (as of May 2024) the canonical place for describing the interaction
+between Cargo and --check-cfg. It is placed in the rustc book rather than the Cargo book
+since check-cfg is primarely a Rust/rustc feature and is therefor consider by T-cargo to
+be an implementation detail, at least --check-cfg and the unexpected_cfgs are owned by
+rustc, not Cargo.
+-->
+
+This document is intented to summarize the principal ways Cargo interacts with
+the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide
+individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and
+to the [Cargo book](../../cargo/index.html).
+
+## Cargo feature
+
+*See the [`[features]` section in the Cargo book][cargo-features] for more details.*
+
+With the `[features]` table Cargo provides a mechanism to express conditional compilation and
+optional dependencies. Cargo *automatically* declares corresponding cfgs for every feature as
+expected.
+
+`Cargo.toml`:
+```toml
+[features]
+serde = ["dep:serde"]
+my_feature = []
+```
+
+[cargo-features]: ../../cargo/reference/features.html
+
+## `check-cfg` in `[lints.rust]` table
+
+<!-- Note that T-Cargo considers `[lints.rust.unexpected_cfgs.check-cfg]` to be an
+implementation detail and is therefor not documented in Cargo, we therefor do that ourself -->
+
+*See the [`[lints]` section in the Cargo book][cargo-lints-table] for more details.*
+
+When using a staticlly known custom config (ie. not dependant on a build-script), Cargo provides
+the custom lint config `check-cfg` under `[lints.rust.unexpected_cfgs]`.
+
+It can be used to set custom static [`--check-cfg`](../check-cfg.md) args, it is mainly useful when
+the list of expected cfgs is known is advance.
+
+`Cargo.toml`:
+```toml
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo)'] }
+```
+
+[cargo-lints-table]: ../../cargo/reference/manifest.html#the-lints-section
+
+## `cargo::rustc-check-cfg` for `build.rs`/build-script
+
+*See the [`cargo::rustc-check-cfg` section in the Cargo book][cargo-rustc-check-cfg] for more details.*
+
+When setting a custom config with [`cargo::rustc-cfg`][cargo-rustc-cfg], Cargo provides the
+corollary instruction: [`cargo::rustc-check-cfg`][cargo-rustc-check-cfg] to expect custom configs.
+
+`build.rs`:
+```rust,ignore (cannot-test-this-because-has_foo-isnt-declared)
+fn main() {
+    println!("cargo::rustc-check-cfg=cfg(has_foo)");
+    //        ^^^^^^^^^^^^^^^^^^^^^^ new with Cargo 1.80
+    if has_foo() {
+        println!("cargo::rustc-cfg=has_foo");
+    }
+}
+```
+
+[cargo-rustc-cfg]: ../../cargo/reference/build-scripts.html#rustc-cfg
+[cargo-rustc-check-cfg]: ../../cargo/reference/build-scripts.html#rustc-check-cfg
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 627f03ddf55..a940eda4689 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: no expected values for `feature`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: no expected values for `feature`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -26,8 +26,12 @@ LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `CONFIG_NVME`
   --> $DIR/cargo-feature.rs:26:7
@@ -35,8 +39,12 @@ warning: unexpected `cfg` condition name: `CONFIG_NVME`
 LL | #[cfg(CONFIG_NVME = "m")]
    |       ^^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(CONFIG_NVME, values("m"))'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 9cc5fb6aca0..70d3182eec8 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -26,8 +26,12 @@ LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
    = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `m`
   --> $DIR/cargo-feature.rs:26:7
@@ -38,8 +42,12 @@ LL | #[cfg(CONFIG_NVME = "m")]
    |                     help: there is a expected value with a similar name: `"y"`
    |
    = note: expected values for `CONFIG_NVME` are: `y`
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(CONFIG_NVME, values("m"))'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/diagnotics.cargo.stderr b/tests/ui/check-cfg/diagnotics.cargo.stderr
index 1b7505682da..a440ccaaf58 100644
--- a/tests/ui/check-cfg/diagnotics.cargo.stderr
+++ b/tests/ui/check-cfg/diagnotics.cargo.stderr
@@ -1,62 +1,70 @@
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:8:7
+  --> $DIR/diagnotics.rs:9:7
    |
 LL | #[cfg(featur)]
    |       ^^^^^^ help: there is a config with a similar name: `feature`
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:12:7
+  --> $DIR/diagnotics.rs:13:7
    |
 LL | #[cfg(featur = "foo")]
    |       ^^^^^^^^^^^^^^
    |
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 help: there is a config with a similar name and value
    |
 LL | #[cfg(feature = "foo")]
    |       ~~~~~~~
 
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:16:7
+  --> $DIR/diagnotics.rs:17:7
    |
 LL | #[cfg(featur = "fo")]
    |       ^^^^^^^^^^^^^
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 help: there is a config with a similar name and different values
    |
 LL | #[cfg(feature = "foo")]
    |       ~~~~~~~~~~~~~~~
 
 warning: unexpected `cfg` condition name: `no_value`
-  --> $DIR/diagnotics.rs:23:7
+  --> $DIR/diagnotics.rs:24:7
    |
 LL | #[cfg(no_value)]
    |       ^^^^^^^^ help: there is a config with a similar name: `no_values`
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value)");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(no_value)'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(no_value)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `no_value`
-  --> $DIR/diagnotics.rs:27:7
+  --> $DIR/diagnotics.rs:28:7
    |
 LL | #[cfg(no_value = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(no_value, values("foo"))'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 help: there is a config with a similar name and no value
    |
 LL | #[cfg(no_values)]
    |       ~~~~~~~~~
 
 warning: unexpected `cfg` condition value: `bar`
-  --> $DIR/diagnotics.rs:31:7
+  --> $DIR/diagnotics.rs:32:7
    |
 LL | #[cfg(no_values = "bar")]
    |       ^^^^^^^^^--------
@@ -64,8 +72,28 @@ LL | #[cfg(no_values = "bar")]
    |                help: remove the value
    |
    = note: no expected value for `no_values`
-   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of the `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(no_values, values("bar"))'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 
-warning: 6 warnings emitted
+warning: unexpected `cfg` condition value: `quote"`
+  --> $DIR/diagnotics.rs:36:7
+   |
+LL | #[cfg(quote = "quote\"")]
+   |       ^^^^^^^^---------
+   |               |
+   |               help: there is a expected value with a similar name: `"quote"`
+   |
+   = note: expected values for `quote` are: `quote`
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(quote, values("quote\""))'] }
+   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(quote, values(\"quote\\\"\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+
+warning: 7 warnings emitted
 
diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs
index b8268ec5606..7155d7c81b9 100644
--- a/tests/ui/check-cfg/diagnotics.rs
+++ b/tests/ui/check-cfg/diagnotics.rs
@@ -4,6 +4,7 @@
 //@ [rustc]unset-rustc-env:CARGO_CRATE_NAME
 //@ [cargo]rustc-env:CARGO_CRATE_NAME=foo
 //@ compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values)
+//@ compile-flags: --check-cfg=cfg(quote,values("quote"))
 
 #[cfg(featur)]
 //~^ WARNING unexpected `cfg` condition name
@@ -32,4 +33,8 @@ fn no_values() {}
 //~^ WARNING unexpected `cfg` condition value
 fn no_values() {}
 
+#[cfg(quote = "quote\"")]
+//~^ WARNING unexpected `cfg` condition value
+fn no_values() {}
+
 fn main() {}
diff --git a/tests/ui/check-cfg/diagnotics.rustc.stderr b/tests/ui/check-cfg/diagnotics.rustc.stderr
index 0bd6ce156bb..6868be482d8 100644
--- a/tests/ui/check-cfg/diagnotics.rustc.stderr
+++ b/tests/ui/check-cfg/diagnotics.rustc.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:8:7
+  --> $DIR/diagnotics.rs:9:7
    |
 LL | #[cfg(featur)]
    |       ^^^^^^ help: there is a config with a similar name: `feature`
@@ -10,7 +10,7 @@ LL | #[cfg(featur)]
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:12:7
+  --> $DIR/diagnotics.rs:13:7
    |
 LL | #[cfg(featur = "foo")]
    |       ^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | #[cfg(feature = "foo")]
    |       ~~~~~~~
 
 warning: unexpected `cfg` condition name: `featur`
-  --> $DIR/diagnotics.rs:16:7
+  --> $DIR/diagnotics.rs:17:7
    |
 LL | #[cfg(featur = "fo")]
    |       ^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL | #[cfg(feature = "foo")]
    |       ~~~~~~~~~~~~~~~
 
 warning: unexpected `cfg` condition name: `no_value`
-  --> $DIR/diagnotics.rs:23:7
+  --> $DIR/diagnotics.rs:24:7
    |
 LL | #[cfg(no_value)]
    |       ^^^^^^^^ help: there is a config with a similar name: `no_values`
@@ -46,7 +46,7 @@ LL | #[cfg(no_value)]
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `no_value`
-  --> $DIR/diagnotics.rs:27:7
+  --> $DIR/diagnotics.rs:28:7
    |
 LL | #[cfg(no_value = "foo")]
    |       ^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL | #[cfg(no_values)]
    |       ~~~~~~~~~
 
 warning: unexpected `cfg` condition value: `bar`
-  --> $DIR/diagnotics.rs:31:7
+  --> $DIR/diagnotics.rs:32:7
    |
 LL | #[cfg(no_values = "bar")]
    |       ^^^^^^^^^--------
@@ -70,5 +70,17 @@ LL | #[cfg(no_values = "bar")]
    = help: to expect this configuration use `--check-cfg=cfg(no_values, values("bar"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
-warning: 6 warnings emitted
+warning: unexpected `cfg` condition value: `quote"`
+  --> $DIR/diagnotics.rs:36:7
+   |
+LL | #[cfg(quote = "quote\"")]
+   |       ^^^^^^^^---------
+   |               |
+   |               help: there is a expected value with a similar name: `"quote"`
+   |
+   = note: expected values for `quote` are: `quote`
+   = help: to expect this configuration use `--check-cfg=cfg(quote, values("quote\""))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: 7 warnings emitted