about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-03-30 10:01:22 -0700
committerEsteban Küber <esteban@kuber.com.ar>2021-04-06 19:55:44 -0700
commitd326c218efaa598e35ede0ef0607ac8e4eb9fea1 (patch)
tree900ea9c3d5e7f6461bdc4ced3782fd37bbdd3aa3
parent16143d10679537d3fde4247e15334e78ad9d55b9 (diff)
downloadrust-d326c218efaa598e35ede0ef0607ac8e4eb9fea1.tar.gz
rust-d326c218efaa598e35ede0ef0607ac8e4eb9fea1.zip
Suggest Pin/Box/Arc for more cases
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs105
1 files changed, 53 insertions, 52 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 72eff009473..02fe8312c4c 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -987,59 +987,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let mut alt_rcvr_sugg = false;
         if let SelfSource::MethodCall(rcvr) = source {
-            info!(?span, ?item_name, ?rcvr_ty, ?rcvr);
-            if let ty::Adt(..) = rcvr_ty.kind() {
-                // 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.
-                for (rcvr_ty, post) in &[
-                    (rcvr_ty, ""),
-                    (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
-                    (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
+            debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
+            // 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.
+            for (rcvr_ty, post) in &[
+                (rcvr_ty, ""),
+                (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
+                (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
+            ] {
+                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"),
+                    (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
+                    (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
                 ] {
-                    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"),
-                        (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
-                        (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
-                    ] {
-                        if let Some(new_rcvr_t) = *rcvr_ty {
-                            if let Ok(pick) = self.lookup_probe(
-                                span,
-                                item_name,
-                                new_rcvr_t,
-                                rcvr,
-                                crate::check::method::probe::ProbeScope::AllTraits,
-                            ) {
-                                debug!("try_alt_rcvr: pick candidate {:?}", pick);
-                                // 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`
-                                if pick.autoderefs == 0
-                                    // We don't want to suggest a container type when the missing method is
-                                    // `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
-                                    // far from what the user really wants.
-                                    && Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
-                                {
-                                    err.span_label(
-                                        pick.item.ident.span,
-                                        &format!(
-                                            "the method is available for `{}` here",
-                                            new_rcvr_t
-                                        ),
-                                    );
-                                    err.multipart_suggestion(
-                                        "consider wrapping the receiver expression with the \
-                                         appropriate type",
-                                        vec![
-                                            (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
-                                            (rcvr.span.shrink_to_hi(), ")".to_string()),
-                                        ],
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                    // We don't care about the other suggestions.
-                                    alt_rcvr_sugg = true;
-                                }
+                    if let Some(new_rcvr_t) = *rcvr_ty {
+                        if let Ok(pick) = self.lookup_probe(
+                            span,
+                            item_name,
+                            new_rcvr_t,
+                            rcvr,
+                            crate::check::method::probe::ProbeScope::AllTraits,
+                        ) {
+                            debug!("try_alt_rcvr: pick candidate {:?}", pick);
+                            let did = Some(pick.item.container.id());
+                            // 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);
+                            // 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`
+                            if pick.autoderefs == 0 && !skip {
+                                err.span_label(
+                                    pick.item.ident.span,
+                                    &format!("the method is available for `{}` here", new_rcvr_t),
+                                );
+                                err.multipart_suggestion(
+                                    "consider wrapping the receiver expression with the \
+                                        appropriate type",
+                                    vec![
+                                        (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
+                                        (rcvr.span.shrink_to_hi(), ")".to_string()),
+                                    ],
+                                    Applicability::MaybeIncorrect,
+                                );
+                                // We don't care about the other suggestions.
+                                alt_rcvr_sugg = true;
                             }
                         }
                     }