Account for Box::new(impl Future)
and emit help use Box::pin
This commit is contained in:
parent
a852fb7413
commit
80cdb0af7d
5 changed files with 84 additions and 30 deletions
|
@ -24,8 +24,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.annotate_expected_due_to_let_ty(err, expr);
|
||||
self.suggest_compatible_variants(err, expr, expected, expr_ty);
|
||||
self.suggest_ref_or_into(err, expr, expected, expr_ty);
|
||||
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
|
||||
return;
|
||||
}
|
||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_await(err, expr, expected, expr_ty);
|
||||
}
|
||||
|
||||
|
|
|
@ -5053,18 +5053,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expr: &hir::Expr<'_>,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) {
|
||||
) -> bool {
|
||||
// Handle #68197.
|
||||
|
||||
if self.tcx.hir().is_const_context(expr.hir_id) {
|
||||
// Do not suggest `Box::new` in const context.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let pin_did = self.tcx.lang_items().pin_type();
|
||||
match expected.kind {
|
||||
ty::Adt(def, _) if Some(def.did) != pin_did => return,
|
||||
ty::Adt(def, _) if Some(def.did) != pin_did => return false,
|
||||
// This guards the `unwrap` and `mk_box` below.
|
||||
_ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return,
|
||||
_ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false,
|
||||
_ => {}
|
||||
}
|
||||
let boxed_found = self.tcx.mk_box(found);
|
||||
|
@ -5073,12 +5073,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.can_coerce(new_found, expected),
|
||||
self.sess().source_map().span_to_snippet(expr.span),
|
||||
) {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
"you need to pin and box this expression",
|
||||
format!("Box::pin({})", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
match found.kind {
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
err.help("use `Box::pin`");
|
||||
}
|
||||
_ => {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
"you need to pin and box this expression",
|
||||
format!("Box::pin({})", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
// edition:2018
|
||||
// run-rustfix
|
||||
#![allow(dead_code)]
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
// ^^^^^^^^^ This would come from the `futures` crate in real code.
|
||||
|
||||
fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
// We could instead use an `async` block, but this way we have no std spans.
|
||||
Box::pin(x) //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,5 +1,4 @@
|
|||
// edition:2018
|
||||
// run-rustfix
|
||||
#![allow(dead_code)]
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
@ -11,5 +10,17 @@ fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32>
|
|||
// We could instead use an `async` block, but this way we have no std spans.
|
||||
x //~ ERROR mismatched types
|
||||
}
|
||||
fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
Box::new(x) //~ ERROR mismatched types
|
||||
//~^ HELP use `Box::pin`
|
||||
}
|
||||
fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
Pin::new(x) //~ ERROR mismatched types
|
||||
//~^ ERROR the trait bound
|
||||
}
|
||||
fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
Pin::new(Box::new(x)) //~ ERROR mismatched types
|
||||
//~^ ERROR the trait bound
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:12:5
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:11:5
|
||||
|
|
||||
LL | fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
| - this type parameter ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
|
||||
|
@ -15,6 +15,52 @@ LL | x
|
|||
= help: type parameters must be constrained to match other types
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:14:5
|
||||
|
|
||||
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
| ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
|
||||
LL | Box::new(x)
|
||||
| ^^^^^^^^^^^ expected struct `std::pin::Pin`, found struct `std::boxed::Box`
|
||||
|
|
||||
= note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>`
|
||||
found struct `std::boxed::Box<F>`
|
||||
= help: use `Box::pin`
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:18:14
|
||||
|
|
||||
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
| - this type parameter
|
||||
LL | Pin::new(x)
|
||||
| ^
|
||||
| |
|
||||
| expected struct `std::boxed::Box`, found type parameter `F`
|
||||
| help: store this in the heap by calling `Box::new`: `Box::new(x)`
|
||||
|
|
||||
= note: expected struct `std::boxed::Box<dyn std::future::Future<Output = i32> + std::marker::Send>`
|
||||
found type parameter `F`
|
||||
= help: type parameters must be constrained to match other types
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
|
||||
error[E0277]: the trait bound `dyn std::future::Future<Output = i32> + std::marker::Send: std::marker::Unpin` is not satisfied
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:18:5
|
||||
|
|
||||
LL | Pin::new(x)
|
||||
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
||||
|
|
||||
= note: required by `std::pin::Pin::<P>::new`
|
||||
|
||||
error[E0277]: the trait bound `dyn std::future::Future<Output = i32> + std::marker::Send: std::marker::Unpin` is not satisfied
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:22:5
|
||||
|
|
||||
LL | Pin::new(Box::new(x))
|
||||
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::future::Future<Output = i32> + std::marker::Send`
|
||||
|
|
||||
= note: required by `std::pin::Pin::<P>::new`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue