about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src/astconv/mod.rs
diff options
context:
space:
mode:
authortrevyn <230691+trevyn@users.noreply.github.com>2024-02-03 10:37:28 -0800
committertrevyn <230691+trevyn@users.noreply.github.com>2024-02-03 19:29:28 -0800
commita4cb55f2aca24f3cbf33b025c147d7a894bceefd (patch)
tree909d6cc14f3b37e3a4d8dd127078e22ea46b34d4 /compiler/rustc_hir_analysis/src/astconv/mod.rs
parentbf3c6c5bed498f41ad815641319a1ad9bcecb8e8 (diff)
downloadrust-a4cb55f2aca24f3cbf33b025c147d7a894bceefd.tar.gz
rust-a4cb55f2aca24f3cbf33b025c147d7a894bceefd.zip
For E0223, suggest methods that look similar to the path
Diffstat (limited to 'compiler/rustc_hir_analysis/src/astconv/mod.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 89f39897ea8..d69f366a66c 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
+use rustc_middle::query::Key;
 use rustc_middle::ty::{
     self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty,
     TyCtxt, TypeVisitableExt,
@@ -1373,6 +1374,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     )
                     .emit() // Already reported in an earlier stage.
                 } else {
+                    // suggest methods that look similar to the path
+                    // e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195)
+                    for (_, node) in tcx.hir().parent_iter(qself.hir_id) {
+                        if let hir::Node::Expr(hir::Expr {
+                            kind:
+                                hir::ExprKind::Path(hir::QPath::TypeRelative(
+                                    hir::Ty {
+                                        kind:
+                                            hir::TyKind::Path(hir::QPath::TypeRelative(
+                                                _,
+                                                hir::PathSegment { ident: ident2, .. },
+                                            )),
+                                        ..
+                                    },
+                                    hir::PathSegment { ident: ident3, .. },
+                                )),
+                            ..
+                        }) = node
+                        {
+                            let name = format!("{ident2}_{ident3}");
+                            if if let Some(ty_def_id) = qself_ty.ty_def_id()
+                                && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
+                                && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
+                                    .associated_items(inherent_impl)
+                                    .filter_by_name_unhygienic(Symbol::intern(&name))
+                                    .next()
+                            {
+                                true
+                            } else {
+                                qself_ty.is_str()
+                                    && ["from_utf8", "from_utf8_mut"].contains(&name.as_str())
+                            } {
+                                let reported = struct_span_code_err!(
+                                    tcx.dcx(),
+                                    span,
+                                    E0223,
+                                    "ambiguous associated type"
+                                )
+                                .with_span_suggestion_verbose(
+                                    ident2.span.to(ident3.span),
+                                    format!("you might have meant to use `{name}`"),
+                                    name,
+                                    Applicability::MaybeIncorrect,
+                                )
+                                .emit();
+                                self.set_tainted_by_errors(reported);
+                                return Err(reported);
+                            }
+                        }
+                    }
+
                     let traits: Vec<_> =
                         self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);