Skip to content

Commit 85ff888

Browse files
committed
Tweak wording
1 parent 34b9594 commit 85ff888

File tree

3 files changed

+98
-30
lines changed

3 files changed

+98
-30
lines changed

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -335,29 +335,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
335335
}
336336
let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
337337
let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
338-
let self_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(base).unwrap();
339-
let pick = self
338+
let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
339+
340+
let Ok(pick) = self
340341
.probe_for_name(
341342
probe::Mode::MethodCall,
342343
path.ident,
343344
probe::IsSuggestion(true),
344345
self_ty,
345346
deref.hir_id,
346347
probe::ProbeScope::TraitsInScope,
347-
)
348-
.unwrap();
349-
let methods = self.probe_for_name_many(
348+
) else {
349+
return;
350+
};
351+
let in_scope_methods = self.probe_for_name_many(
352+
probe::Mode::MethodCall,
353+
path.ident,
354+
probe::IsSuggestion(true),
355+
self_ty,
356+
deref.hir_id,
357+
probe::ProbeScope::TraitsInScope,
358+
);
359+
let other_methods_in_scope: Vec<_> =
360+
in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
361+
362+
let all_methods = self.probe_for_name_many(
350363
probe::Mode::MethodCall,
351364
path.ident,
352365
probe::IsSuggestion(true),
353366
self_ty,
354367
deref.hir_id,
355368
probe::ProbeScope::AllTraits,
356369
);
357-
let suggestions: Vec<_> = methods
370+
let suggestions: Vec<_> = all_methods
358371
.into_iter()
359-
.filter(|m| m.def_id != pick.item.def_id)
360-
.map(|m| {
372+
.filter(|c| c.item.def_id != pick.item.def_id)
373+
.map(|c| {
374+
let m = c.item;
361375
let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
362376
self.var_for_def(deref.span, param)
363377
});
@@ -389,21 +403,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
389403
let mut path_span: MultiSpan = path.ident.span.into();
390404
path_span.push_span_label(
391405
path.ident.span,
392-
format!(
406+
with_no_trimmed_paths!(format!(
393407
"refers to `{}`",
394-
with_no_trimmed_paths!(self.tcx.def_path_str(pick.item.def_id)),
395-
),
408+
self.tcx.def_path_str(pick.item.def_id),
409+
)),
396410
);
411+
let container_id = pick.item.container_id(self.tcx);
412+
let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
413+
for def_id in pick.import_ids {
414+
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
415+
path_span.push_span_label(
416+
self.tcx.hir().span(hir_id),
417+
format!("`{container}` imported here"),
418+
);
419+
}
420+
let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
421+
[] => return,
422+
[candidate] => format!(
423+
"the method of the same name on {} `{}`",
424+
match candidate.kind {
425+
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
426+
_ => "trait",
427+
},
428+
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
429+
),
430+
[.., last] if other_methods_in_scope.len() < 5 => {
431+
format!(
432+
"the methods of the same name on {} and `{}`",
433+
other_methods_in_scope[..other_methods_in_scope.len() - 1]
434+
.iter()
435+
.map(|c| format!(
436+
"`{}`",
437+
self.tcx.def_path_str(c.item.container_id(self.tcx))
438+
))
439+
.collect::<Vec<String>>()
440+
.join(", "),
441+
self.tcx.def_path_str(last.item.container_id(self.tcx))
442+
)
443+
}
444+
_ => format!(
445+
"the methods of the same name on {} other traits",
446+
other_methods_in_scope.len()
447+
),
448+
});
397449
err.span_note(
398450
path_span,
399451
&format!(
400-
"there are multiple methods with the same name, `{}` refers to `{}` in the method call",
401-
path.ident,
402-
with_no_trimmed_paths!(self.tcx.def_path_str(pick.item.def_id)),
403-
));
452+
"the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
453+
path.ident,
454+
),
455+
);
456+
if suggestions.len() > other_methods_in_scope.len() {
457+
err.note(&format!(
458+
"additionally, there are {} other available methods that aren't in scope",
459+
suggestions.len() - other_methods_in_scope.len()
460+
));
461+
}
404462
err.multipart_suggestions(
405-
"you might have meant to invoke a different method, you can use the fully-qualified path",
406-
suggestions,
463+
&format!(
464+
"you might have meant to call {}; you can use the fully-qualified path to call {} \
465+
explicitly",
466+
if suggestions.len() == 1 {
467+
"the other method"
468+
} else {
469+
"one of the other methods"
470+
},
471+
if suggestions.len() == 1 { "it" } else { "one of them" },
472+
),
473+
suggestions,
407474
Applicability::MaybeIncorrect,
408475
);
409476
}

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
9797
}
9898

9999
#[derive(Debug, Clone)]
100-
struct Candidate<'tcx> {
100+
pub(crate) struct Candidate<'tcx> {
101101
// Candidates are (I'm not quite sure, but they are mostly) basically
102102
// some metadata on top of a `ty::AssocItem` (without substs).
103103
//
@@ -131,13 +131,13 @@ struct Candidate<'tcx> {
131131
// if `T: Sized`.
132132
xform_self_ty: Ty<'tcx>,
133133
xform_ret_ty: Option<Ty<'tcx>>,
134-
item: ty::AssocItem,
135-
kind: CandidateKind<'tcx>,
136-
import_ids: SmallVec<[LocalDefId; 1]>,
134+
pub(crate) item: ty::AssocItem,
135+
pub(crate) kind: CandidateKind<'tcx>,
136+
pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
137137
}
138138

139139
#[derive(Debug, Clone)]
140-
enum CandidateKind<'tcx> {
140+
pub(crate) enum CandidateKind<'tcx> {
141141
InherentImplCandidate(
142142
SubstsRef<'tcx>,
143143
// Normalize obligations
@@ -323,15 +323,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323323
}
324324

325325
#[instrument(level = "debug", skip(self))]
326-
pub fn probe_for_name_many(
326+
pub(crate) fn probe_for_name_many(
327327
&self,
328328
mode: Mode,
329329
item_name: Ident,
330330
is_suggestion: IsSuggestion,
331331
self_ty: Ty<'tcx>,
332332
scope_expr_id: hir::HirId,
333333
scope: ProbeScope,
334-
) -> Vec<ty::AssocItem> {
334+
) -> Vec<Candidate<'tcx>> {
335335
self.probe_op(
336336
item_name.span,
337337
mode,
@@ -344,10 +344,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
344344
|probe_cx| {
345345
Ok(probe_cx
346346
.inherent_candidates
347-
.iter()
348-
.chain(&probe_cx.extension_candidates)
349-
// .filter(|candidate| candidate_filter(&candidate.item))
350-
.map(|candidate| candidate.item)
347+
.into_iter()
348+
.chain(probe_cx.extension_candidates)
351349
.collect())
352350
},
353351
)

src/test/ui/suggestions/shadowed-lplace-method.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ LL | *rc.borrow_mut() = false;
88
|
99
= note: expected struct `Rc<RefCell<bool>>`
1010
found type `bool`
11-
note: there are multiple methods with the same name, `borrow_mut` refers to `std::borrow::BorrowMut::borrow_mut` in the method call
11+
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>`
1212
--> $DIR/shadowed-lplace-method.rs:9:9
1313
|
14+
LL | use std::borrow::BorrowMut;
15+
| ---------------------- `std::borrow::BorrowMut` imported here
16+
...
1417
LL | *rc.borrow_mut() = false;
1518
| ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut`
16-
help: you might have meant to invoke a different method, you can use the fully-qualified path
19+
help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
1720
|
1821
LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false;
1922
| +++++++++++++++++++++++++++++++++++++ ~

0 commit comments

Comments
 (0)