Skip to content

Commit 6b58fbf

Browse files
committed
rebase and review comments
1 parent 2c3fd1a commit 6b58fbf

File tree

3 files changed

+25
-12
lines changed

3 files changed

+25
-12
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -2496,13 +2496,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24962496
// FIXME: probe for all types that *could* be arbitrary self-types, not
24972497
// just this list.
24982498
for (rcvr_ty, post, pin_call) in &[
2499-
(rcvr_ty, "", ""),
2499+
(rcvr_ty, "", None),
25002500
(
25012501
Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
25022502
"&mut ",
2503-
"as_mut",
2503+
Some("as_mut"),
2504+
),
2505+
(
2506+
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
2507+
"&",
2508+
Some("as_ref"),
25042509
),
2505-
(Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&", "as_ref"),
25062510
] {
25072511
match self.lookup_probe_for_diagnostic(
25082512
item_name,
@@ -2594,22 +2598,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25942598
}
25952599
}
25962600
}
2597-
// We special case the situation where `Pin::new` wouldn't work, and isntead
2601+
// We special case the situation where `Pin::new` wouldn't work, and instead
25982602
// suggest using the `pin!()` macro instead.
25992603
if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin)
2604+
// We didn't find an alternative receiver for the method.
26002605
&& !alt_rcvr_sugg
2606+
// `T: !Unpin`
26012607
&& !unpin
2608+
// The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`.
26022609
&& sym::as_ref != item_name.name
2603-
&& *pin_call != ""
2610+
// Either `Pin::as_ref` or `Pin::as_mut`.
2611+
&& let Some(pin_call) = pin_call
2612+
// Search for `item_name` as a method accessible on `Pin<T>`.
26042613
&& let Ok(pick) = self.lookup_probe_for_diagnostic(
26052614
item_name,
26062615
new_rcvr_t,
26072616
rcvr,
26082617
ProbeScope::AllTraits,
26092618
return_type,
26102619
)
2620+
// We skip some common traits that we don't want to consider because autoderefs
2621+
// would take care of them.
26112622
&& !skippable.contains(&Some(pick.item.container_id(self.tcx)))
2623+
// We don't want to go through derefs.
26122624
&& pick.autoderefs == 0
2625+
// Check that the method of the same name that was found on the new `Pin<T>`
2626+
// receiver has the same number of arguments that appear in the user's code.
26132627
&& 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)
26142628
{
26152629
let indent = self.tcx.sess

tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ impl S {
88
}
99

1010
fn main() {
11-
Pin::new(&mut S).x(); //~ ERROR no method named `x` found
11+
let mut pinned = std::pin::pin!(S);
12+
pinned.as_mut().x(); //~ ERROR no method named `x` found
1213
}

tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ error[E0599]: no method named `x` found for struct `S` in the current scope
44
LL | struct S;
55
| -------- method `x` not found for this struct
66
...
7-
LL | fn x(self: Pin<&mut Self>) {
8-
| - the method is available for `Pin<&mut S>` here
9-
...
107
LL | S.x();
118
| ^ method not found in `S`
129
|
13-
help: consider wrapping the receiver expression with the appropriate type
10+
help: consider pinning the expression
11+
|
12+
LL ~ let mut pinned = std::pin::pin!(S);
13+
LL ~ pinned.as_mut().x();
1414
|
15-
LL | Pin::new(&mut S).x();
16-
| +++++++++++++ +
1715

1816
error: aborting due to previous error
1917

0 commit comments

Comments
 (0)