mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #125684 - estebank:pin-to-binding-suggestion, r=pnkfelix
Account for existing bindings when suggesting `pin!()` When we encounter a situation where we'd suggest `pin!()`, we now account for that expression existing as part of an assignment and provide an appropriate suggestion: ``` error[E0599]: no method named `poll` found for type parameter `F` in the current scope --> $DIR/pin-needed-to-poll-3.rs:19:28 | LL | impl<F> Future for FutureWrapper<F> | - method `poll` not found for this type parameter ... LL | let res = self.fut.poll(cx); | ^^^^ method not found in `F` | help: consider pinning the expression | LL ~ let mut pinned = std::pin::pin!(self.fut); LL ~ let res = pinned.as_mut().poll(cx); | ``` Fix #125661.
This commit is contained in:
commit
260f789ae1
@ -3360,14 +3360,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.source_map()
|
||||
.indentation_before(rcvr.span)
|
||||
.unwrap_or_else(|| " ".to_string());
|
||||
err.multipart_suggestion(
|
||||
"consider pinning the expression",
|
||||
vec![
|
||||
(rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")),
|
||||
(rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let mut expr = rcvr;
|
||||
while let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
|
||||
&& let hir::ExprKind::MethodCall(hir::PathSegment { .. }, ..) =
|
||||
call_expr.kind
|
||||
{
|
||||
expr = call_expr;
|
||||
}
|
||||
match self.tcx.parent_hir_node(expr.hir_id) {
|
||||
Node::LetStmt(stmt)
|
||||
if let Some(init) = stmt.init
|
||||
&& let Ok(code) =
|
||||
self.tcx.sess.source_map().span_to_snippet(rcvr.span) =>
|
||||
{
|
||||
// We need to take care to account for the existing binding when we
|
||||
// suggest the code.
|
||||
err.multipart_suggestion(
|
||||
"consider pinning the expression",
|
||||
vec![
|
||||
(
|
||||
stmt.span.shrink_to_lo(),
|
||||
format!(
|
||||
"let mut pinned = std::pin::pin!({code});\n{indent}"
|
||||
),
|
||||
),
|
||||
(
|
||||
init.span.until(rcvr.span.shrink_to_hi()),
|
||||
format!("pinned.{pin_call}()"),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
Node::Block(_) | Node::Stmt(_) => {
|
||||
// There's no binding, so we can provide a slightly nicer looking
|
||||
// suggestion.
|
||||
err.multipart_suggestion(
|
||||
"consider pinning the expression",
|
||||
vec![
|
||||
(
|
||||
rcvr.span.shrink_to_lo(),
|
||||
format!("let mut pinned = std::pin::pin!("),
|
||||
),
|
||||
(
|
||||
rcvr.span.shrink_to_hi(),
|
||||
format!(");\n{indent}pinned.{pin_call}()"),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
// We don't quite know what the users' code looks like, so we don't
|
||||
// provide a pinning suggestion.
|
||||
err.span_help(
|
||||
rcvr.span,
|
||||
"consider pinning the expression with `std::pin::pin!()` and \
|
||||
assigning that to a new binding",
|
||||
);
|
||||
}
|
||||
}
|
||||
// We don't care about the other suggestions.
|
||||
alt_rcvr_sugg = true;
|
||||
}
|
||||
|
25
tests/ui/async-await/pin-needed-to-poll-3.rs
Normal file
25
tests/ui/async-await/pin-needed-to-poll-3.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
|
||||
struct FutureWrapper<F> {
|
||||
fut: F,
|
||||
}
|
||||
|
||||
impl<F> Future for FutureWrapper<F>
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let res = self.fut.poll(cx);
|
||||
//~^ ERROR no method named `poll` found for type parameter `F` in the current scope
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
18
tests/ui/async-await/pin-needed-to-poll-3.stderr
Normal file
18
tests/ui/async-await/pin-needed-to-poll-3.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error[E0599]: no method named `poll` found for type parameter `F` in the current scope
|
||||
--> $DIR/pin-needed-to-poll-3.rs:19:28
|
||||
|
|
||||
LL | impl<F> Future for FutureWrapper<F>
|
||||
| - method `poll` not found for this type parameter
|
||||
...
|
||||
LL | let res = self.fut.poll(cx);
|
||||
| ^^^^ method not found in `F`
|
||||
|
|
||||
help: consider pinning the expression
|
||||
|
|
||||
LL ~ let mut pinned = std::pin::pin!(self.fut);
|
||||
LL ~ let res = pinned.as_mut().poll(cx);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
Loading…
Reference in New Issue
Block a user