From 6b58fbfd7ecb7a7ea90065aae0f307f903c0ce54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 14 Aug 2023 21:40:11 +0000 Subject: [PATCH] rebase and review comments --- .../rustc_hir_typeck/src/method/suggest.rs | 24 +++++++++++++++---- ...arbitrary_self_types_needing_mut_pin.fixed | 3 ++- ...rbitrary_self_types_needing_mut_pin.stderr | 10 ++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3ea2d310b0f..770adb6fc7d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2496,13 +2496,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: probe for all types that *could* be arbitrary self-types, not // just this list. for (rcvr_ty, post, pin_call) in &[ - (rcvr_ty, "", ""), + (rcvr_ty, "", None), ( Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&mut ", - "as_mut", + Some("as_mut"), + ), + ( + Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), + "&", + Some("as_ref"), ), - (Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&", "as_ref"), ] { match self.lookup_probe_for_diagnostic( item_name, @@ -2594,13 +2598,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - // We special case the situation where `Pin::new` wouldn't work, and isntead + // We special case the situation where `Pin::new` wouldn't work, and instead // suggest using the `pin!()` macro instead. if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin) + // We didn't find an alternative receiver for the method. && !alt_rcvr_sugg + // `T: !Unpin` && !unpin + // The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`. && sym::as_ref != item_name.name - && *pin_call != "" + // Either `Pin::as_ref` or `Pin::as_mut`. + && let Some(pin_call) = pin_call + // Search for `item_name` as a method accessible on `Pin`. && let Ok(pick) = self.lookup_probe_for_diagnostic( item_name, new_rcvr_t, @@ -2608,8 +2617,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::AllTraits, return_type, ) + // We skip some common traits that we don't want to consider because autoderefs + // would take care of them. && !skippable.contains(&Some(pick.item.container_id(self.tcx))) + // We don't want to go through derefs. && pick.autoderefs == 0 + // Check that the method of the same name that was found on the new `Pin` + // receiver has the same number of arguments that appear in the user's code. && inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len) { let indent = self.tcx.sess diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed index ccd65ff4091..a400a1672a4 100644 --- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed +++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed @@ -8,5 +8,6 @@ impl S { } fn main() { - Pin::new(&mut S).x(); //~ ERROR no method named `x` found + let mut pinned = std::pin::pin!(S); + pinned.as_mut().x(); //~ ERROR no method named `x` found } diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr index f34ce4dce49..5dcb5861120 100644 --- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr +++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr @@ -4,16 +4,14 @@ error[E0599]: no method named `x` found for struct `S` in the current scope LL | struct S; | -------- method `x` not found for this struct ... -LL | fn x(self: Pin<&mut Self>) { - | - the method is available for `Pin<&mut S>` here -... LL | S.x(); | ^ method not found in `S` | -help: consider wrapping the receiver expression with the appropriate type +help: consider pinning the expression + | +LL ~ let mut pinned = std::pin::pin!(S); +LL ~ pinned.as_mut().x(); | -LL | Pin::new(&mut S).x(); - | +++++++++++++ + error: aborting due to previous error