From 204ba3224ef06f99622fd733cdc14afbc5d83c7e Mon Sep 17 00:00:00 2001 From: yifei Date: Wed, 8 Mar 2023 20:12:46 +0800 Subject: [PATCH] fix: evaluate with wrong obligation stack --- .../src/traits/select/mod.rs | 4 ++-- tests/ui/traits/unsend-future.rs | 21 ++++++++++++++++ tests/ui/traits/unsend-future.stderr | 24 +++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/unsend-future.rs create mode 100644 tests/ui/traits/unsend-future.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cd3f3c114ba1e..48c3b3601b4d3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1083,7 +1083,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested_result = EvaluationResult::EvaluatedToOk; for obligation in nested_obligations { nested_result = cmp::max( - this.evaluate_predicate_recursively(stack.list(), obligation)?, + this.evaluate_predicate_recursively(previous_stack, obligation)?, nested_result, ); } @@ -1092,7 +1092,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation = obligation.with(this.tcx(), predicate); result = cmp::max( nested_result, - this.evaluate_trait_predicate_recursively(stack.list(), obligation)?, + this.evaluate_trait_predicate_recursively(previous_stack, obligation)?, ); } } diff --git a/tests/ui/traits/unsend-future.rs b/tests/ui/traits/unsend-future.rs new file mode 100644 index 0000000000000..fbbc07b11e743 --- /dev/null +++ b/tests/ui/traits/unsend-future.rs @@ -0,0 +1,21 @@ +// edition:2021 + +// issue 108897 +trait Handler {} +impl Handler for F +where + Fut: Send, + F: FnOnce() -> Fut, +{} + +fn require_handler(h: H) {} + +async fn handler() { + let a = &1 as *const i32; + async {}.await; +} + +fn main() { + require_handler(handler) + //~^ ERROR future cannot be sent between threads safely +} diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr new file mode 100644 index 0000000000000..4aaa7c4a92426 --- /dev/null +++ b/tests/ui/traits/unsend-future.stderr @@ -0,0 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/unsend-future.rs:19:21 + | +LL | require_handler(handler) + | ^^^^^^^ future returned by `handler` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `*const i32` +note: future is not `Send` as this value is used across an await + --> $DIR/unsend-future.rs:15:13 + | +LL | let a = &1 as *const i32; + | - has type `*const i32` which is not `Send` +LL | async {}.await; + | ^^^^^^ await occurs here, with `a` maybe used later +LL | } + | - `a` is later dropped here +note: required by a bound in `require_handler` + --> $DIR/unsend-future.rs:11:23 + | +LL | fn require_handler(h: H) {} + | ^^^^^^^ required by this bound in `require_handler` + +error: aborting due to previous error +