-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Do not consider async
task_context
to be alive across yields
When lowering async constructs to generators, the resume argument is guaranteed not to be alive across yield points. However the simple `generator_interior` analysis thinks it is. Because of that, the resume ty was part of the `GeneratorWitness` and considered to be part of the generator type, even though it is not really. This prevented async blocks from being `UnwindSafe`, and possibly `Send` in some cases. The code now special cases the fact that the `task_context` of async blocks is never alive across yield points.
- Loading branch information
Showing
9 changed files
with
135 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// edition:2018 | ||
|
||
fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} | ||
|
||
fn main() { | ||
// a normal async block that uses `&mut Context<'_>` implicitly via async lowering is fine | ||
// as we should not consider that to be alive across an await point | ||
is_unwindsafe(async { | ||
async {}.await; // this needs an inner await point | ||
}); | ||
|
||
is_unwindsafe(async { | ||
//~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary | ||
use std::ptr::null; | ||
use std::task::{Context, RawWaker, RawWakerVTable, Waker}; | ||
let waker = unsafe { | ||
Waker::from_raw(RawWaker::new( | ||
null(), | ||
&RawWakerVTable::new(|_| todo!(), |_| todo!(), |_| todo!(), |_| todo!()), | ||
)) | ||
}; | ||
let mut cx = Context::from_waker(&waker); | ||
let cx_ref = &mut cx; | ||
|
||
async {}.await; // this needs an inner await point | ||
|
||
// in this case, `&mut Context<'_>` is *truely* alive across an await point | ||
drop(cx_ref); | ||
drop(cx); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary | ||
--> $DIR/async-is-unwindsafe.rs:12:19 | ||
| | ||
LL | is_unwindsafe(async { | ||
| ___________________^ | ||
LL | | | ||
LL | | use std::ptr::null; | ||
LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker}; | ||
... | | ||
LL | | drop(cx); | ||
LL | | }); | ||
| | ^ | ||
| | | | ||
| |_____`&mut Context<'_>` may not be safely transferred across an unwind boundary | ||
| within this `[async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6]` | ||
| | ||
= help: within `[async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6]`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` | ||
= note: `UnwindSafe` is implemented for `&std::task::Context<'_>`, but not for `&mut std::task::Context<'_>` | ||
note: future does not implement `UnwindSafe` as this value is used across an await | ||
--> $DIR/async-is-unwindsafe.rs:25:17 | ||
| | ||
LL | let cx_ref = &mut cx; | ||
| ------ has type `&mut Context<'_>` which does not implement `UnwindSafe` | ||
LL | | ||
LL | async {}.await; // this needs an inner await point | ||
| ^^^^^^ await occurs here, with `cx_ref` maybe used later | ||
... | ||
LL | }); | ||
| - `cx_ref` is later dropped here | ||
note: required by a bound in `is_unwindsafe` | ||
--> $DIR/async-is-unwindsafe.rs:3:26 | ||
| | ||
LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe` | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0277`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters