1
Fork 0

Rollup merge of #84499 - estebank:issue-84272, r=jackh726

Tweak trait not `use`d suggestion

Fix #84272. Follow up to #83667.
This commit is contained in:
Dylan DPC 2021-04-25 23:15:13 +02:00 committed by GitHub
commit ae316d6603
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 96 additions and 8 deletions

View file

@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut alt_rcvr_sugg = false;
if let SelfSource::MethodCall(rcvr) = source {
debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
let skippable = [
self.tcx.lang_items().clone_trait(),
self.tcx.lang_items().deref_trait(),
self.tcx.lang_items().deref_mut_trait(),
self.tcx.lang_items().drop_trait(),
];
// Try alternative arbitrary self types that could fulfill this call.
// FIXME: probe for all types that *could* be arbitrary self-types, not
// just this list.
@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
] {
if let Ok(pick) = self.lookup_probe(
span,
item_name,
rcvr_ty,
rcvr,
crate::check::method::probe::ProbeScope::AllTraits,
) {
// If the method is defined for the receiver we have, it likely wasn't `use`d.
// We point at the method, but we just skip the rest of the check for arbitrary
// self types and rely on the suggestion to `use` the trait from
// `suggest_valid_traits`.
let did = Some(pick.item.container.id());
let skip = skippable.contains(&did);
if pick.autoderefs == 0 && !skip {
err.span_label(
pick.item.ident.span,
&format!("the method is available for `{}` here", rcvr_ty),
);
}
break;
}
for (rcvr_ty, pre) in &[
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We don't want to suggest a container type when the missing
// method is `.clone()` or `.deref()` otherwise we'd suggest
// `Arc::new(foo).clone()`, which is far from what the user wants.
let skip = [
self.tcx.lang_items().clone_trait(),
self.tcx.lang_items().deref_trait(),
self.tcx.lang_items().deref_mut_trait(),
self.tcx.lang_items().drop_trait(),
]
.contains(&did);
let skip = skippable.contains(&did);
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
@ -1047,7 +1068,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) {
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
return;
}