about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-02-14 18:11:19 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-02-22 18:05:28 +0000
commitb59bd7fd16d6dfd3d09d1d708325d39763ec0ec7 (patch)
tree437c5fb6deb9efa2e852b0d3baeb0bacda7ffad6
parentf566867ace85044ef80f73cf9c214876a5aa4e77 (diff)
downloadrust-b59bd7fd16d6dfd3d09d1d708325d39763ec0ec7.tar.gz
rust-b59bd7fd16d6dfd3d09d1d708325d39763ec0ec7.zip
review comments: clean up
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs137
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs189
2 files changed, 166 insertions, 160 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 0ca7a8bb47b..612f645d5d5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -563,80 +563,73 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let suggest_confusable = |err: &mut Diagnostic| {
-            if let Some(call_name) = call_ident
-                && let Some(callee_ty) = callee_ty
+            let call_name = call_ident?;
+            let callee_ty = callee_ty?;
+            let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
+            // Check for other methods in the following order
+            //  - methods marked as `rustc_confusables` with the provided arguments
+            //  - methods with the same argument type/count and short levenshtein distance
+            //  - methods marked as `rustc_confusables` (done)
+            //  - methods with short levenshtein distance
+
+            // Look for commonly confusable method names considering arguments.
+            if let Some(name) = self.confusable_method_name(
+                err,
+                callee_ty.peel_refs(),
+                call_name,
+                Some(input_types.clone()),
+            ) {
+                return Some(name);
+            }
+            // Look for method names with short levenshtein distance, considering arguments.
+            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
+                && fn_sig.inputs()[1..]
+                    .iter()
+                    .zip(input_types.iter())
+                    .all(|(expected, found)| self.can_coerce(*expected, *found))
+                && fn_sig.inputs()[1..].len() == input_types.len()
             {
-                let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
-                // Check for other methods in the following order
-                //  - methods marked as `rustc_confusables` with the provided arguments
-                //  - methods with the same argument type/count and short levenshtein distance
-                //  - methods marked as `rustc_confusables` (done)
-                //  - methods with short levenshtein distance
-
-                // Look for commonly confusable method names considering arguments.
-                self.confusable_method_name(
-                    err,
-                    callee_ty.peel_refs(),
-                    call_name,
-                    Some(input_types.clone()),
-                )
-                .or_else(|| {
-                    // Look for method names with short levenshtein distance, considering arguments.
-                    if let Some((assoc, fn_sig)) = similar_assoc(call_name)
-                        && fn_sig.inputs()[1..]
-                            .iter()
-                            .zip(input_types.iter())
-                            .all(|(expected, found)| self.can_coerce(*expected, *found))
-                        && fn_sig.inputs()[1..].len() == input_types.len()
-                    {
-                        err.span_suggestion_verbose(
-                            call_name.span,
-                            format!("you might have meant to use `{}`", assoc.name),
-                            assoc.name,
-                            Applicability::MaybeIncorrect,
-                        );
-                        return Some(assoc.name);
-                    }
-                    None
-                })
-                .or_else(|| {
-                    // Look for commonly confusable method names disregarding arguments.
-                    self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
-                })
-                .or_else(|| {
-                    // Look for similarly named methods with levenshtein distance with the right
-                    // number of arguments.
-                    if let Some((assoc, fn_sig)) = similar_assoc(call_name)
-                        && fn_sig.inputs()[1..].len() == input_types.len()
-                    {
-                        err.span_note(
-                            tcx.def_span(assoc.def_id),
-                            format!(
-                                "there's is a method with similar name `{}`, but the arguments \
-                                 don't match",
-                                assoc.name,
-                            ),
-                        );
-                        return Some(assoc.name);
-                    }
-                    None
-                })
-                .or_else(|| {
-                    // Fallthrough: look for similarly named methods with levenshtein distance.
-                    if let Some((assoc, _)) = similar_assoc(call_name) {
-                        err.span_note(
-                            tcx.def_span(assoc.def_id),
-                            format!(
-                                "there's is a method with similar name `{}`, but their argument \
-                                 count doesn't match",
-                                assoc.name,
-                            ),
-                        );
-                        return Some(assoc.name);
-                    }
-                    None
-                });
+                err.span_suggestion_verbose(
+                    call_name.span,
+                    format!("you might have meant to use `{}`", assoc.name),
+                    assoc.name,
+                    Applicability::MaybeIncorrect,
+                );
+                return Some(assoc.name);
+            }
+            // Look for commonly confusable method names disregarding arguments.
+            if let Some(name) =
+                self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
+            {
+                return Some(name);
+            }
+            // Look for similarly named methods with levenshtein distance with the right
+            // number of arguments.
+            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
+                && fn_sig.inputs()[1..].len() == input_types.len()
+            {
+                err.span_note(
+                    tcx.def_span(assoc.def_id),
+                    format!(
+                        "there's is a method with similar name `{}`, but the arguments don't match",
+                        assoc.name,
+                    ),
+                );
+                return Some(assoc.name);
             }
+            // Fallthrough: look for similarly named methods with levenshtein distance.
+            if let Some((assoc, _)) = similar_assoc(call_name) {
+                err.span_note(
+                    tcx.def_span(assoc.def_id),
+                    format!(
+                        "there's is a method with similar name `{}`, but their argument count \
+                         doesn't match",
+                        assoc.name,
+                    ),
+                );
+                return Some(assoc.name);
+            }
+            None
         };
         // A "softer" version of the `demand_compatible`, which checks types without persisting them,
         // and treats error types differently
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 2196daa9878..ae40cb29ed6 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1358,94 +1358,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ...or if we already suggested that name because of `rustc_confusable` annotation.
                 && Some(similar_candidate.name) != confusable_suggested
             {
-                let def_kind = similar_candidate.kind.as_def_kind();
-                let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
-                // Methods are defined within the context of a struct and their first parameter
-                // is always `self`, which represents the instance of the struct the method is
-                // being called on Associated functions don’t take self as a parameter and they are
-                // not methods because they don’t have an instance of the struct to work with.
-                if def_kind == DefKind::AssocFn {
-                    let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
-                    let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
-                    let fn_sig =
-                        self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig);
-                    if similar_candidate.fn_has_self_parameter {
-                        if let Some(args) = args
-                            && fn_sig.inputs()[1..].len() == args.len()
-                        {
-                            // We found a method with the same number of arguments as the method
-                            // call expression the user wrote.
-                            err.span_suggestion_verbose(
-                                span,
-                                format!("there is {an} method with a similar name"),
-                                similar_candidate.name,
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            // We found a method but either the expression is not a method call or
-                            // the argument count didn't match.
-                            err.span_help(
-                                tcx.def_span(similar_candidate.def_id),
-                                format!(
-                                    "there is {an} method `{}` with a similar name{}",
-                                    similar_candidate.name,
-                                    if let None = args {
-                                        ""
-                                    } else {
-                                        ", but with different arguments"
-                                    },
-                                ),
-                            );
-                        }
-                    } else if let Some(args) = args
-                        && fn_sig.inputs().len() == args.len()
-                    {
-                        // We have fn call expression and the argument count match the associated
-                        // function we found.
-                        err.span_suggestion_verbose(
-                            span,
-                            format!(
-                                "there is {an} {} with a similar name",
-                                self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
-                            ),
-                            similar_candidate.name,
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        err.span_help(
-                            tcx.def_span(similar_candidate.def_id),
-                            format!(
-                                "there is {an} {} `{}` with a similar name",
-                                self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
-                                similar_candidate.name,
-                            ),
-                        );
-                    }
-                } else if let Mode::Path = mode
-                    && args.unwrap_or(&[]).is_empty()
-                {
-                    // We have an associated item syntax and we found something that isn't an fn.
-                    err.span_suggestion_verbose(
-                        span,
-                        format!(
-                            "there is {an} {} with a similar name",
-                            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
-                        ),
-                        similar_candidate.name,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    // The expression is a function or method call, but the item we found is an
-                    // associated const or type.
-                    err.span_help(
-                        tcx.def_span(similar_candidate.def_id),
-                        format!(
-                            "there is {an} {} `{}` with a similar name",
-                            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
-                            similar_candidate.name,
-                        ),
-                    );
-                }
+                self.find_likely_intended_associated_item(
+                    &mut err,
+                    similar_candidate,
+                    span,
+                    args,
+                    mode,
+                );
             }
         }
         // If an appropriate error source is not found, check method chain for possible candiates
@@ -1497,6 +1416,100 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Some(err)
     }
 
+    fn find_likely_intended_associated_item(
+        &self,
+        err: &mut Diagnostic,
+        similar_candidate: ty::AssocItem,
+        span: Span,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
+        mode: Mode,
+    ) {
+        let tcx = self.tcx;
+        let def_kind = similar_candidate.kind.as_def_kind();
+        let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
+        // Methods are defined within the context of a struct and their first parameter
+        // is always `self`, which represents the instance of the struct the method is
+        // being called on Associated functions don’t take self as a parameter and they are
+        // not methods because they don’t have an instance of the struct to work with.
+        if def_kind == DefKind::AssocFn {
+            let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
+            let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
+            let fn_sig = self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig);
+            if similar_candidate.fn_has_self_parameter {
+                if let Some(args) = args
+                    && fn_sig.inputs()[1..].len() == args.len()
+                {
+                    // We found a method with the same number of arguments as the method
+                    // call expression the user wrote.
+                    err.span_suggestion_verbose(
+                        span,
+                        format!("there is {an} method with a similar name"),
+                        similar_candidate.name,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    // We found a method but either the expression is not a method call or
+                    // the argument count didn't match.
+                    err.span_help(
+                        tcx.def_span(similar_candidate.def_id),
+                        format!(
+                            "there is {an} method `{}` with a similar name{}",
+                            similar_candidate.name,
+                            if let None = args { "" } else { ", but with different arguments" },
+                        ),
+                    );
+                }
+            } else if let Some(args) = args
+                && fn_sig.inputs().len() == args.len()
+            {
+                // We have fn call expression and the argument count match the associated
+                // function we found.
+                err.span_suggestion_verbose(
+                    span,
+                    format!(
+                        "there is {an} {} with a similar name",
+                        self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
+                    ),
+                    similar_candidate.name,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                err.span_help(
+                    tcx.def_span(similar_candidate.def_id),
+                    format!(
+                        "there is {an} {} `{}` with a similar name",
+                        self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
+                        similar_candidate.name,
+                    ),
+                );
+            }
+        } else if let Mode::Path = mode
+            && args.unwrap_or(&[]).is_empty()
+        {
+            // We have an associated item syntax and we found something that isn't an fn.
+            err.span_suggestion_verbose(
+                span,
+                format!(
+                    "there is {an} {} with a similar name",
+                    self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
+                ),
+                similar_candidate.name,
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            // The expression is a function or method call, but the item we found is an
+            // associated const or type.
+            err.span_help(
+                tcx.def_span(similar_candidate.def_id),
+                format!(
+                    "there is {an} {} `{}` with a similar name",
+                    self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
+                    similar_candidate.name,
+                ),
+            );
+        }
+    }
+
     pub(crate) fn confusable_method_name(
         &self,
         err: &mut Diagnostic,