about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/context/diagnostics.rs
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-03-16 23:33:54 +0100
committerUrgau <urgau@numericable.fr>2024-03-16 23:33:54 +0100
commitbf8715e6eedcbb64c86c6357c5adeb059f322d35 (patch)
tree7c0dbaac4867942e0074a711723be38890f24279 /compiler/rustc_lint/src/context/diagnostics.rs
parentfe6157522848604562f83084154274c545fe3a27 (diff)
downloadrust-bf8715e6eedcbb64c86c6357c5adeb059f322d35.tar.gz
rust-bf8715e6eedcbb64c86c6357c5adeb059f322d35.zip
Move check-cfg diagnostic logic into it's own module
Diffstat (limited to 'compiler/rustc_lint/src/context/diagnostics.rs')
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs279
1 files changed, 5 insertions, 274 deletions
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index a0be1c09c9a..e2010ab3830 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -5,49 +5,11 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
 use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag};
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_middle::middle::stability;
-use rustc_session::config::ExpectedValues;
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::Session;
-use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::symbol::{sym, Symbol};
 use rustc_span::BytePos;
 
-const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
-
-fn check_cfg_expected_note(
-    sess: &Session,
-    possibilities: &[Symbol],
-    type_: &str,
-    name: Option<Symbol>,
-    suffix: &str,
-) -> String {
-    use std::fmt::Write;
-
-    let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
-        possibilities.len()
-    } else {
-        std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
-    };
-
-    let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-    possibilities.sort();
-
-    let and_more = possibilities.len().saturating_sub(n_possibilities);
-    let possibilities = possibilities[..n_possibilities].join("`, `");
-
-    let mut note = String::with_capacity(50 + possibilities.len());
-
-    write!(&mut note, "expected {type_}").unwrap();
-    if let Some(name) = name {
-        write!(&mut note, " for `{name}`").unwrap();
-    }
-    write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
-    if and_more > 0 {
-        write!(&mut note, " and {and_more} more").unwrap();
-    }
-
-    note
-}
+mod check_cfg;
 
 pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
     match diagnostic {
@@ -219,242 +181,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             diag.help(help);
             diag.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");
         }
-        BuiltinLintDiag::UnexpectedCfgName((name, name_span), value) => {
-            #[allow(rustc::potential_query_instability)]
-            let possibilities: Vec<Symbol> =
-                sess.psess.check_config.expecteds.keys().copied().collect();
-
-            let mut names_possibilities: Vec<_> = if value.is_none() {
-                // We later sort and display all the possibilities, so the order here does not matter.
-                #[allow(rustc::potential_query_instability)]
-                sess.psess
-                    .check_config
-                    .expecteds
-                    .iter()
-                    .filter_map(|(k, v)| match v {
-                        ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
-                        _ => None,
-                    })
-                    .collect()
-            } else {
-                Vec::new()
-            };
-
-            let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
-            let mut is_feature_cfg = name == sym::feature;
-
-            if is_feature_cfg && is_from_cargo {
-                diag.help("consider defining some features in `Cargo.toml`");
-            // Suggest the most probable if we found one
-            } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
-                if let Some(ExpectedValues::Some(best_match_values)) =
-                    sess.psess.check_config.expecteds.get(&best_match)
-                {
-                    // We will soon sort, so the initial order does not matter.
-                    #[allow(rustc::potential_query_instability)]
-                    let mut possibilities =
-                        best_match_values.iter().flatten().map(Symbol::as_str).collect::<Vec<_>>();
-                    possibilities.sort();
-
-                    let mut should_print_possibilities = true;
-                    if let Some((value, value_span)) = value {
-                        if best_match_values.contains(&Some(value)) {
-                            diag.span_suggestion(
-                                name_span,
-                                "there is a config with a similar name and value",
-                                best_match,
-                                Applicability::MaybeIncorrect,
-                            );
-                            should_print_possibilities = false;
-                        } else if best_match_values.contains(&None) {
-                            diag.span_suggestion(
-                                name_span.to(value_span),
-                                "there is a config with a similar name and no value",
-                                best_match,
-                                Applicability::MaybeIncorrect,
-                            );
-                            should_print_possibilities = false;
-                        } else if let Some(first_value) = possibilities.first() {
-                            diag.span_suggestion(
-                                name_span.to(value_span),
-                                "there is a config with a similar name and different values",
-                                format!("{best_match} = \"{first_value}\""),
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            diag.span_suggestion(
-                                name_span.to(value_span),
-                                "there is a config with a similar name and different values",
-                                best_match,
-                                Applicability::MaybeIncorrect,
-                            );
-                        };
-                    } else {
-                        diag.span_suggestion(
-                            name_span,
-                            "there is a config with a similar name",
-                            best_match,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-
-                    if !possibilities.is_empty() && should_print_possibilities {
-                        let possibilities = possibilities.join("`, `");
-                        diag.help(format!(
-                            "expected values for `{best_match}` are: `{possibilities}`"
-                        ));
-                    }
-                } else {
-                    diag.span_suggestion(
-                        name_span,
-                        "there is a config with a similar name",
-                        best_match,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-
-                is_feature_cfg |= best_match == sym::feature;
-            } else {
-                if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
-                    names_possibilities.sort();
-                    for cfg_name in names_possibilities.iter() {
-                        diag.span_suggestion(
-                            name_span,
-                            "found config with similar value",
-                            format!("{cfg_name} = \"{name}\""),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-                if !possibilities.is_empty() {
-                    diag.help_once(check_cfg_expected_note(
-                        sess,
-                        &possibilities,
-                        "names",
-                        None,
-                        "",
-                    ));
-                }
-            }
-
-            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})")
-            };
-
-            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 a `build.rs`"));
-                }
-                diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
-            } else {
-                diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
-                diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
-            }
+        BuiltinLintDiag::UnexpectedCfgName(name, value) => {
+            check_cfg::unexpected_cfg_name(sess, diag, name, value)
         }
-        BuiltinLintDiag::UnexpectedCfgValue((name, name_span), value) => {
-            let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name)
-            else {
-                bug!(
-                    "it shouldn't be possible to have a diagnostic on a value whose name is not in values"
-                );
-            };
-            let mut have_none_possibility = false;
-            // We later sort possibilities if it is not empty, so the
-            // order here does not matter.
-            #[allow(rustc::potential_query_instability)]
-            let possibilities: Vec<Symbol> = values
-                .iter()
-                .inspect(|a| have_none_possibility |= a.is_none())
-                .copied()
-                .flatten()
-                .collect();
-            let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
-
-            // 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 !possibilities.is_empty() {
-                diag.note(check_cfg_expected_note(
-                    sess,
-                    &possibilities,
-                    "values",
-                    Some(name),
-                    if have_none_possibility { "(none), " } else { "" },
-                ));
-
-                if let Some((value, value_span)) = value {
-                    // Suggest the most probable if we found one
-                    if let Some(best_match) = find_best_match_for_name(&possibilities, value, None)
-                    {
-                        diag.span_suggestion(
-                            value_span,
-                            "there is a expected value with a similar name",
-                            format!("\"{best_match}\""),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                } else if let &[first_possibility] = &possibilities[..] {
-                    diag.span_suggestion(
-                        name_span.shrink_to_hi(),
-                        "specify a config value",
-                        format!(" = \"{first_possibility}\""),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            } else if have_none_possibility {
-                diag.note(format!("no expected value for `{name}`"));
-                if let Some((_value, value_span)) = value {
-                    diag.span_suggestion(
-                        name_span.shrink_to_hi().to(value_span),
-                        "remove the value",
-                        "",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            } else {
-                diag.note(format!("no expected values for `{name}`"));
-
-                let sp = if let Some((_value, value_span)) = value {
-                    name_span.to(value_span)
-                } else {
-                    name_span
-                };
-                diag.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
-            }
-
-            // We don't want to suggest adding values to well known names
-            // since those are defined by rustc it-self. Users can still
-            // 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})")
-            };
-
-            if is_from_cargo {
-                if name == sym::feature {
-                    if let Some((value, _value_span)) = value {
-                        diag.help(format!(
-                            "consider adding `{value}` as a feature in `Cargo.toml`"
-                        ));
-                    } else {
-                        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 a `build.rs`"));
-                }
-                diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> 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}`"));
-                }
-                diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
-            }
+        BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
+            check_cfg::unexpected_cfg_value(sess, diag, name, value)
         }
         BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
             let left_sp = diag.span.primary_span().unwrap();