]> git.lizzy.rs Git - rust.git/commitdiff
Improve diagnostic of the unexpected_cfgs lint
authorLoïc BRANSTETT <lolo.branstett@numericable.fr>
Sat, 19 Feb 2022 23:48:10 +0000 (00:48 +0100)
committerLoïc BRANSTETT <lolo.branstett@numericable.fr>
Tue, 22 Feb 2022 22:17:13 +0000 (23:17 +0100)
compiler/rustc_attr/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint_defs/src/lib.rs
src/test/ui/check-cfg/invalid-cfg-name.stderr
src/test/ui/check-cfg/invalid-cfg-value.stderr
src/test/ui/check-cfg/well-known-names.stderr

index cd2e150a1907d51eef88d36a807cfd01664d892f..503e172b6873ff1017ba0bfd637ee99e64c28b43 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_session::lint::builtin::UNEXPECTED_CFGS;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::Session;
 use rustc_span::hygiene::Transparency;
@@ -465,11 +466,16 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                 let value = cfg.value_str();
                 if let Some(names_valid) = &sess.check_config.names_valid {
                     if !names_valid.contains(&name) {
-                        sess.buffer_lint(
+                        sess.buffer_lint_with_diagnostic(
                             UNEXPECTED_CFGS,
                             cfg.span,
                             CRATE_NODE_ID,
                             "unexpected `cfg` condition name",
+                            BuiltinLintDiagnostics::UnexpectedCfg(
+                                cfg.ident().unwrap().span,
+                                name,
+                                None,
+                            ),
                         );
                     }
                 }
@@ -477,11 +483,16 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                     if let Some(values_valid) = &sess.check_config.values_valid {
                         if let Some(values) = values_valid.get(&name) {
                             if !values.contains(&val) {
-                                sess.buffer_lint(
+                                sess.buffer_lint_with_diagnostic(
                                     UNEXPECTED_CFGS,
                                     cfg.span,
                                     CRATE_NODE_ID,
                                     "unexpected `cfg` condition value",
+                                    BuiltinLintDiagnostics::UnexpectedCfg(
+                                        cfg.name_value_literal_span().unwrap(),
+                                        name,
+                                        Some(val),
+                                    ),
                                 );
                             }
                         }
index d2d853efda2d25db2c69b2d029118b65939c5c76..72a3f5d5fc9b8ed3ca25acaa02b749d8dc5bf140 100644 (file)
@@ -766,7 +766,39 @@ fn lookup_with_diagnostics(
                 BuiltinLintDiagnostics::NamedAsmLabel(help) => {
                     db.help(&help);
                     db.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
-                }
+                },
+                BuiltinLintDiagnostics::UnexpectedCfg(span, name, value) => {
+                    let mut possibilities: Vec<Symbol> = if value.is_some() {
+                        let Some(values_valid) = &sess.parse_sess.check_config.values_valid else {
+                            bug!("it shouldn't be possible to have a diagnostic on a value if values checking is not enable");
+                        };
+                        let Some(values) = values_valid.get(&name) else {
+                            bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values");
+                        };
+                        values.iter().map(|&s| s).collect()
+                    } else {
+                        let Some(names_valid) = &sess.parse_sess.check_config.names_valid else {
+                            bug!("it shouldn't be possible to have a diagnostic on a value if values checking is not enable");
+                        };
+                        names_valid.iter().map(|s| *s).collect()
+                    };
+
+                    // Show the full list if all possible values for a given name, but don't do it
+                    // for names as the possibilities could be very long
+                    if value.is_some() {
+                        // Sorting can take some time, so we only do it if required
+                        possibilities.sort();
+
+                        let possibilities = possibilities.iter().map(Symbol::as_str).intersperse(", ").collect::<String>();
+                        db.note(&format!("possible values for `{name}` are: {possibilities}"));
+                    }
+
+                    // Suggest the most probable if we found one
+                    if let Some(best_match) = find_best_match_for_name(&possibilities, value.unwrap_or(name), None) {
+                        let ponctuation = if value.is_some() { "\"" } else { "" };
+                        db.span_suggestion(span, "did you mean", format!("{ponctuation}{best_match}{ponctuation}"), Applicability::MaybeIncorrect);
+                    }
+                },
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
index 69863b5ff827fcd27fcbbdd3714db3e9ee16cb6c..7182022d2529817d5f7bf9163e3d21289adccb6a 100644 (file)
@@ -31,6 +31,7 @@
 #![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
 #![feature(if_let_guard)]
+#![feature(iter_intersperse)]
 #![feature(iter_order_by)]
 #![feature(let_else)]
 #![feature(never_type)]
index 1f834b7212fe58c697561b8e505b80e05c44c979..e9c62fc40065158ee61d38e29eec72663a17a6f5 100644 (file)
@@ -310,6 +310,7 @@ pub enum BuiltinLintDiagnostics {
     BreakWithLabelAndLoop(Span),
     NamedAsmLabel(String),
     UnicodeTextFlow(Span, String),
+    UnexpectedCfg(Span, Symbol, Option<Symbol>),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
index 2587685afa048a66ed27f66973ecfbb01a13fed0..2bd1821c9422b79ae60e1e631dfce6329f31b0b0 100644 (file)
@@ -2,7 +2,7 @@ warning: unexpected `cfg` condition name
   --> $DIR/invalid-cfg-name.rs:7:7
    |
 LL | #[cfg(widnows)]
-   |       ^^^^^^^
+   |       ^^^^^^^ help: did you mean: `windows`
    |
    = note: `#[warn(unexpected_cfgs)]` on by default
 
index c591d8474a26146a0ece257f3a6a65c302f70685..23fd5c8c759cf2022f9c302e5bfbec6553ab9192 100644 (file)
@@ -5,6 +5,7 @@ LL | #[cfg(feature = "sedre")]
    |       ^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: possible values for `feature` are: rand, serde, full
 
 warning: 1 warning emitted
 
index a6b9a77dc8d9a8419ea4c5e6fc6f497edfd67a26..bdbe4d29d30feb07d00579bb4149581fdcd70f84 100644 (file)
@@ -2,7 +2,9 @@ warning: unexpected `cfg` condition name
   --> $DIR/well-known-names.rs:6:7
    |
 LL | #[cfg(target_oz = "linux")]
-   |       ^^^^^^^^^^^^^^^^^^^
+   |       ---------^^^^^^^^^^
+   |       |
+   |       help: did you mean: `target_os`
    |
    = note: `#[warn(unexpected_cfgs)]` on by default
 
@@ -10,13 +12,15 @@ warning: unexpected `cfg` condition name
   --> $DIR/well-known-names.rs:13:7
    |
 LL | #[cfg(features = "foo")]
-   |       ^^^^^^^^^^^^^^^^
+   |       --------^^^^^^^^
+   |       |
+   |       help: did you mean: `feature`
 
 warning: unexpected `cfg` condition name
   --> $DIR/well-known-names.rs:20:7
    |
 LL | #[cfg(uniw)]
-   |       ^^^^
+   |       ^^^^ help: did you mean: `unix`
 
 warning: 3 warnings emitted