1
Fork 0

Tweak wording

This commit is contained in:
Esteban Küber 2022-12-26 12:00:22 -08:00
parent 34b9594f6d
commit 85ff8889e4
3 changed files with 98 additions and 30 deletions

View file

@ -335,8 +335,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; }; let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; }; let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
let self_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(base).unwrap(); let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
let pick = self
let Ok(pick) = self
.probe_for_name( .probe_for_name(
probe::Mode::MethodCall, probe::Mode::MethodCall,
path.ident, path.ident,
@ -344,9 +345,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty, self_ty,
deref.hir_id, deref.hir_id,
probe::ProbeScope::TraitsInScope, probe::ProbeScope::TraitsInScope,
) ) else {
.unwrap(); return;
let methods = self.probe_for_name_many( };
let in_scope_methods = self.probe_for_name_many(
probe::Mode::MethodCall,
path.ident,
probe::IsSuggestion(true),
self_ty,
deref.hir_id,
probe::ProbeScope::TraitsInScope,
);
let other_methods_in_scope: Vec<_> =
in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
let all_methods = self.probe_for_name_many(
probe::Mode::MethodCall, probe::Mode::MethodCall,
path.ident, path.ident,
probe::IsSuggestion(true), probe::IsSuggestion(true),
@ -354,10 +367,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deref.hir_id, deref.hir_id,
probe::ProbeScope::AllTraits, probe::ProbeScope::AllTraits,
); );
let suggestions: Vec<_> = methods let suggestions: Vec<_> = all_methods
.into_iter() .into_iter()
.filter(|m| m.def_id != pick.item.def_id) .filter(|c| c.item.def_id != pick.item.def_id)
.map(|m| { .map(|c| {
let m = c.item;
let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| { let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
self.var_for_def(deref.span, param) self.var_for_def(deref.span, param)
}); });
@ -389,21 +403,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut path_span: MultiSpan = path.ident.span.into(); let mut path_span: MultiSpan = path.ident.span.into();
path_span.push_span_label( path_span.push_span_label(
path.ident.span, path.ident.span,
format!( with_no_trimmed_paths!(format!(
"refers to `{}`", "refers to `{}`",
with_no_trimmed_paths!(self.tcx.def_path_str(pick.item.def_id)), self.tcx.def_path_str(pick.item.def_id),
), )),
); );
let container_id = pick.item.container_id(self.tcx);
let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
for def_id in pick.import_ids {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
path_span.push_span_label(
self.tcx.hir().span(hir_id),
format!("`{container}` imported here"),
);
}
let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
[] => return,
[candidate] => format!(
"the method of the same name on {} `{}`",
match candidate.kind {
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
_ => "trait",
},
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
),
[.., last] if other_methods_in_scope.len() < 5 => {
format!(
"the methods of the same name on {} and `{}`",
other_methods_in_scope[..other_methods_in_scope.len() - 1]
.iter()
.map(|c| format!(
"`{}`",
self.tcx.def_path_str(c.item.container_id(self.tcx))
))
.collect::<Vec<String>>()
.join(", "),
self.tcx.def_path_str(last.item.container_id(self.tcx))
)
}
_ => format!(
"the methods of the same name on {} other traits",
other_methods_in_scope.len()
),
});
err.span_note( err.span_note(
path_span, path_span,
&format!( &format!(
"there are multiple methods with the same name, `{}` refers to `{}` in the method call", "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
path.ident, path.ident,
with_no_trimmed_paths!(self.tcx.def_path_str(pick.item.def_id)), ),
)); );
if suggestions.len() > other_methods_in_scope.len() {
err.note(&format!(
"additionally, there are {} other available methods that aren't in scope",
suggestions.len() - other_methods_in_scope.len()
));
}
err.multipart_suggestions( err.multipart_suggestions(
"you might have meant to invoke a different method, you can use the fully-qualified path", &format!(
suggestions, "you might have meant to call {}; you can use the fully-qualified path to call {} \
explicitly",
if suggestions.len() == 1 {
"the other method"
} else {
"one of the other methods"
},
if suggestions.len() == 1 { "it" } else { "one of them" },
),
suggestions,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }

View file

@ -97,7 +97,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Candidate<'tcx> { pub(crate) struct Candidate<'tcx> {
// Candidates are (I'm not quite sure, but they are mostly) basically // Candidates are (I'm not quite sure, but they are mostly) basically
// some metadata on top of a `ty::AssocItem` (without substs). // some metadata on top of a `ty::AssocItem` (without substs).
// //
@ -131,13 +131,13 @@ struct Candidate<'tcx> {
// if `T: Sized`. // if `T: Sized`.
xform_self_ty: Ty<'tcx>, xform_self_ty: Ty<'tcx>,
xform_ret_ty: Option<Ty<'tcx>>, xform_ret_ty: Option<Ty<'tcx>>,
item: ty::AssocItem, pub(crate) item: ty::AssocItem,
kind: CandidateKind<'tcx>, pub(crate) kind: CandidateKind<'tcx>,
import_ids: SmallVec<[LocalDefId; 1]>, pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum CandidateKind<'tcx> { pub(crate) enum CandidateKind<'tcx> {
InherentImplCandidate( InherentImplCandidate(
SubstsRef<'tcx>, SubstsRef<'tcx>,
// Normalize obligations // Normalize obligations
@ -323,7 +323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
pub fn probe_for_name_many( pub(crate) fn probe_for_name_many(
&self, &self,
mode: Mode, mode: Mode,
item_name: Ident, item_name: Ident,
@ -331,7 +331,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId, scope_expr_id: hir::HirId,
scope: ProbeScope, scope: ProbeScope,
) -> Vec<ty::AssocItem> { ) -> Vec<Candidate<'tcx>> {
self.probe_op( self.probe_op(
item_name.span, item_name.span,
mode, mode,
@ -344,10 +344,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|probe_cx| { |probe_cx| {
Ok(probe_cx Ok(probe_cx
.inherent_candidates .inherent_candidates
.iter() .into_iter()
.chain(&probe_cx.extension_candidates) .chain(probe_cx.extension_candidates)
// .filter(|candidate| candidate_filter(&candidate.item))
.map(|candidate| candidate.item)
.collect()) .collect())
}, },
) )

View file

@ -8,12 +8,15 @@ LL | *rc.borrow_mut() = false;
| |
= note: expected struct `Rc<RefCell<bool>>` = note: expected struct `Rc<RefCell<bool>>`
found type `bool` found type `bool`
note: there are multiple methods with the same name, `borrow_mut` refers to `std::borrow::BorrowMut::borrow_mut` in the method call note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell<T>`
--> $DIR/shadowed-lplace-method.rs:9:9 --> $DIR/shadowed-lplace-method.rs:9:9
| |
LL | use std::borrow::BorrowMut;
| ---------------------- `std::borrow::BorrowMut` imported here
...
LL | *rc.borrow_mut() = false; LL | *rc.borrow_mut() = false;
| ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut` | ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut`
help: you might have meant to invoke a different method, you can use the fully-qualified path help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
| |
LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false; LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false;
| +++++++++++++++++++++++++++++++++++++ ~ | +++++++++++++++++++++++++++++++++++++ ~