Skip to content

Commit fd66899

Browse files
committed
Suggest Pin/Box/Arc for more cases
1 parent 16156fb commit fd66899

File tree

1 file changed

+53
-52
lines changed

1 file changed

+53
-52
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -987,59 +987,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
987987
) {
988988
let mut alt_rcvr_sugg = false;
989989
if let SelfSource::MethodCall(rcvr) = source {
990-
info!(?span, ?item_name, ?rcvr_ty, ?rcvr);
991-
if let ty::Adt(..) = rcvr_ty.kind() {
992-
// Try alternative arbitrary self types that could fulfill this call.
993-
// FIXME: probe for all types that *could* be arbitrary self-types, not
994-
// just this list.
995-
for (rcvr_ty, post) in &[
996-
(rcvr_ty, ""),
997-
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
998-
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
990+
debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
991+
// Try alternative arbitrary self types that could fulfill this call.
992+
// FIXME: probe for all types that *could* be arbitrary self-types, not
993+
// just this list.
994+
for (rcvr_ty, post) in &[
995+
(rcvr_ty, ""),
996+
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
997+
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
998+
] {
999+
for (rcvr_ty, pre) in &[
1000+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1001+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1002+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1003+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
9991004
] {
1000-
for (rcvr_ty, pre) in &[
1001-
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1002-
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1003-
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1004-
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1005-
] {
1006-
if let Some(new_rcvr_t) = *rcvr_ty {
1007-
if let Ok(pick) = self.lookup_probe(
1008-
span,
1009-
item_name,
1010-
new_rcvr_t,
1011-
rcvr,
1012-
crate::check::method::probe::ProbeScope::AllTraits,
1013-
) {
1014-
debug!("try_alt_rcvr: pick candidate {:?}", pick);
1015-
// Make sure the method is defined for the *actual* receiver:
1016-
// we don't want to treat `Box<Self>` as a receiver if
1017-
// it only works because of an autoderef to `&self`
1018-
if pick.autoderefs == 0
1019-
// We don't want to suggest a container type when the missing method is
1020-
// `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
1021-
// far from what the user really wants.
1022-
&& Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
1023-
{
1024-
err.span_label(
1025-
pick.item.ident.span,
1026-
&format!(
1027-
"the method is available for `{}` here",
1028-
new_rcvr_t
1029-
),
1030-
);
1031-
err.multipart_suggestion(
1032-
"consider wrapping the receiver expression with the \
1033-
appropriate type",
1034-
vec![
1035-
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1036-
(rcvr.span.shrink_to_hi(), ")".to_string()),
1037-
],
1038-
Applicability::MaybeIncorrect,
1039-
);
1040-
// We don't care about the other suggestions.
1041-
alt_rcvr_sugg = true;
1042-
}
1005+
if let Some(new_rcvr_t) = *rcvr_ty {
1006+
if let Ok(pick) = self.lookup_probe(
1007+
span,
1008+
item_name,
1009+
new_rcvr_t,
1010+
rcvr,
1011+
crate::check::method::probe::ProbeScope::AllTraits,
1012+
) {
1013+
debug!("try_alt_rcvr: pick candidate {:?}", pick);
1014+
let did = Some(pick.item.container.id());
1015+
// We don't want to suggest a container type when the missing
1016+
// method is `.clone()` or `.deref()` otherwise we'd suggest
1017+
// `Arc::new(foo).clone()`, which is far from what the user wants.
1018+
let skip = [
1019+
self.tcx.lang_items().clone_trait(),
1020+
self.tcx.lang_items().deref_trait(),
1021+
self.tcx.lang_items().deref_mut_trait(),
1022+
self.tcx.lang_items().drop_trait(),
1023+
]
1024+
.contains(&did);
1025+
// Make sure the method is defined for the *actual* receiver: we don't
1026+
// want to treat `Box<Self>` as a receiver if it only works because of
1027+
// an autoderef to `&self`
1028+
if pick.autoderefs == 0 && !skip {
1029+
err.span_label(
1030+
pick.item.ident.span,
1031+
&format!("the method is available for `{}` here", new_rcvr_t),
1032+
);
1033+
err.multipart_suggestion(
1034+
"consider wrapping the receiver expression with the \
1035+
appropriate type",
1036+
vec![
1037+
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1038+
(rcvr.span.shrink_to_hi(), ")".to_string()),
1039+
],
1040+
Applicability::MaybeIncorrect,
1041+
);
1042+
// We don't care about the other suggestions.
1043+
alt_rcvr_sugg = true;
10431044
}
10441045
}
10451046
}

0 commit comments

Comments
 (0)