forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#62106 - cramertj:test-await, r=centril
Add more tests for async/await I'll follow up with more of these, but here's an initial few. r? @Centril
- Loading branch information
Showing
8 changed files
with
338 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// compile-fail | ||
// edition:2018 | ||
// compile-flags: --crate-type lib | ||
|
||
#![feature(async_await)] | ||
|
||
use std::{ | ||
cell::RefCell, | ||
fmt::Debug, | ||
rc::Rc, | ||
}; | ||
|
||
fn non_sync() -> impl Debug { RefCell::new(()) } | ||
|
||
fn non_send() -> impl Debug { Rc::new(()) } | ||
|
||
fn take_ref<T>(_: &T) {} | ||
|
||
async fn fut() {} | ||
|
||
async fn fut_arg<T>(_: T) {} | ||
|
||
async fn local_dropped_before_await() { | ||
// FIXME: it'd be nice for this to be allowed in a `Send` `async fn` | ||
let x = non_send(); | ||
drop(x); | ||
fut().await; | ||
} | ||
|
||
async fn non_send_temporary_in_match() { | ||
// We could theoretically make this work as well (produce a `Send` future) | ||
// for scrutinees / temporaries that can or will | ||
// be dropped prior to the match body | ||
// (e.g. `Copy` types). | ||
match Some(non_send()) { | ||
Some(_) => fut().await, | ||
None => {} | ||
} | ||
} | ||
|
||
async fn non_sync_with_method_call() { | ||
// FIXME: it'd be nice for this to work. | ||
let f: &mut std::fmt::Formatter = panic!(); | ||
if non_sync().fmt(f).unwrap() == () { | ||
fut().await; | ||
} | ||
} | ||
|
||
fn assert_send(_: impl Send) {} | ||
|
||
pub fn pass_assert() { | ||
assert_send(local_dropped_before_await()); | ||
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely | ||
assert_send(non_send_temporary_in_match()); | ||
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely | ||
assert_send(non_sync_with_method_call()); | ||
//~^ ERROR `dyn std::fmt::Write` cannot be sent between threads safely | ||
//~^^ ERROR `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | ||
} |
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,87 @@ | ||
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely | ||
--> $DIR/async-fn-nonsend.rs:52:5 | ||
| | ||
LL | assert_send(local_dropped_before_await()); | ||
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | ||
| | ||
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` | ||
= note: required because it appears within the type `impl std::fmt::Debug` | ||
= note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}` | ||
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]` | ||
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
note: required by `assert_send` | ||
--> $DIR/async-fn-nonsend.rs:49:1 | ||
| | ||
LL | fn assert_send(_: impl Send) {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely | ||
--> $DIR/async-fn-nonsend.rs:54:5 | ||
| | ||
LL | assert_send(non_send_temporary_in_match()); | ||
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | ||
| | ||
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` | ||
= note: required because it appears within the type `impl std::fmt::Debug` | ||
= note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}` | ||
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]` | ||
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
note: required by `assert_send` | ||
--> $DIR/async-fn-nonsend.rs:49:1 | ||
| | ||
LL | fn assert_send(_: impl Send) {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely | ||
--> $DIR/async-fn-nonsend.rs:56:5 | ||
| | ||
LL | assert_send(non_sync_with_method_call()); | ||
| ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely | ||
| | ||
= help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` | ||
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` | ||
= note: required because it appears within the type `std::fmt::Formatter<'_>` | ||
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` | ||
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` | ||
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` | ||
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
note: required by `assert_send` | ||
--> $DIR/async-fn-nonsend.rs:49:1 | ||
| | ||
LL | fn assert_send(_: impl Send) {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | ||
--> $DIR/async-fn-nonsend.rs:56:5 | ||
| | ||
LL | assert_send(non_sync_with_method_call()); | ||
| ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | ||
| | ||
= help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` | ||
= note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` | ||
= note: required because it appears within the type `core::fmt::Void` | ||
= note: required because it appears within the type `&core::fmt::Void` | ||
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>` | ||
= note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` | ||
= note: required because it appears within the type `std::fmt::Formatter<'_>` | ||
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` | ||
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` | ||
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` | ||
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
= note: required because it appears within the type `impl std::future::Future` | ||
note: required by `assert_send` | ||
--> $DIR/async-fn-nonsend.rs:49:1 | ||
| | ||
LL | fn assert_send(_: impl Send) {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 4 previous errors | ||
|
||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// compile-pass | ||
// edition:2018 | ||
// compile-flags: --crate-type lib | ||
|
||
#![feature(async_await)] | ||
|
||
use std::{ | ||
cell::RefCell, | ||
fmt::Debug, | ||
rc::Rc, | ||
}; | ||
|
||
fn non_sync() -> impl Debug { RefCell::new(()) } | ||
|
||
fn non_send() -> impl Debug { Rc::new(()) } | ||
|
||
fn take_ref<T>(_: &T) {} | ||
|
||
async fn fut() {} | ||
|
||
async fn fut_arg<T>(_: T) {} | ||
|
||
async fn still_send() { | ||
fut().await; | ||
println!("{:?} {:?}", non_send(), non_sync()); | ||
fut().await; | ||
drop(non_send()); | ||
drop(non_sync()); | ||
fut().await; | ||
fut_arg(non_sync()).await; | ||
|
||
// Note: all temporaries in `if let` and `match` scrutinee | ||
// are dropped at the *end* of the blocks, so using `non_send()` | ||
// in either of those positions with an await in the middle will | ||
// cause a `!Send` future. It might be nice in the future to allow | ||
// this for `Copy` types, since they can be "dropped" early without | ||
// affecting the end user. | ||
if let Some(_) = Some(non_sync()) { | ||
fut().await; | ||
} | ||
match Some(non_sync()) { | ||
Some(_) => fut().await, | ||
None => fut().await, | ||
} | ||
|
||
let _ = non_send(); | ||
fut().await; | ||
|
||
{ | ||
let _x = non_send(); | ||
} | ||
fut().await; | ||
} | ||
|
||
fn assert_send(_: impl Send) {} | ||
|
||
pub fn pass_assert() { | ||
assert_send(still_send()); | ||
} |
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,90 @@ | ||
// compile-pass | ||
// edition:2018 | ||
// compile-flags: --crate-type lib | ||
|
||
#![feature(async_await)] | ||
|
||
use std::future::Future; | ||
|
||
pub async fn simple_generic<T>() {} | ||
|
||
pub trait Foo { | ||
fn foo(&self) {} | ||
} | ||
|
||
struct FooType; | ||
impl Foo for FooType {} | ||
|
||
pub async fn call_generic_bound<F: Foo>(f: F) { | ||
f.foo() | ||
} | ||
|
||
pub async fn call_where_clause<F>(f: F) | ||
where | ||
F: Foo, | ||
{ | ||
f.foo() | ||
} | ||
|
||
pub async fn call_impl_trait(f: impl Foo) { | ||
f.foo() | ||
} | ||
|
||
pub async fn call_with_ref(f: &impl Foo) { | ||
f.foo() | ||
} | ||
|
||
pub fn async_fn_with_same_generic_params_unifies() { | ||
let mut a = call_generic_bound(FooType); | ||
a = call_generic_bound(FooType); | ||
|
||
let mut b = call_where_clause(FooType); | ||
b = call_where_clause(FooType); | ||
|
||
let mut c = call_impl_trait(FooType); | ||
c = call_impl_trait(FooType); | ||
|
||
let f_one = FooType; | ||
let f_two = FooType; | ||
let mut d = call_with_ref(&f_one); | ||
d = call_with_ref(&f_two); | ||
} | ||
|
||
pub fn simple_generic_block<T>() -> impl Future<Output = ()> { | ||
async move {} | ||
} | ||
|
||
pub fn call_generic_bound_block<F: Foo>(f: F) -> impl Future<Output = ()> { | ||
async move { f.foo() } | ||
} | ||
|
||
pub fn call_where_clause_block<F>(f: F) -> impl Future<Output = ()> | ||
where | ||
F: Foo, | ||
{ | ||
async move { f.foo() } | ||
} | ||
|
||
pub fn call_impl_trait_block(f: impl Foo) -> impl Future<Output = ()> { | ||
async move { f.foo() } | ||
} | ||
|
||
pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a { | ||
async move { f.foo() } | ||
} | ||
|
||
pub fn async_block_with_same_generic_params_unifies() { | ||
let mut a = call_generic_bound_block(FooType); | ||
a = call_generic_bound_block(FooType); | ||
|
||
let mut b = call_where_clause_block(FooType); | ||
b = call_where_clause_block(FooType); | ||
|
||
let mut c = call_impl_trait_block(FooType); | ||
c = call_impl_trait_block(FooType); | ||
|
||
let f_one = FooType; | ||
let f_two = FooType; | ||
let mut d = call_with_ref_block(&f_one); | ||
d = call_with_ref_block(&f_two); | ||
} |
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,8 @@ | ||
// compile-fail | ||
// edition:2018 | ||
// compile-flags: --crate-type lib | ||
|
||
#![feature(async_await)] | ||
|
||
pub async const fn x() {} | ||
//~^ ERROR expected one of `fn` or `unsafe`, found `const` |
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,8 @@ | ||
error: expected one of `fn` or `unsafe`, found `const` | ||
--> $DIR/no-async-const.rs:7:11 | ||
| | ||
LL | pub async const fn x() {} | ||
| ^^^^^ expected one of `fn` or `unsafe` here | ||
|
||
error: aborting due to previous error | ||
|
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,9 @@ | ||
// compile-fail | ||
// edition:2018 | ||
// compile-flags: --crate-type lib | ||
|
||
#![feature(async_await)] | ||
|
||
pub const async fn x() {} | ||
//~^ ERROR expected identifier, found reserved keyword `async` | ||
//~^^ expected `:`, found keyword `fn` |
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,18 @@ | ||
error: expected identifier, found reserved keyword `async` | ||
--> $DIR/no-const-async.rs:7:11 | ||
| | ||
LL | pub const async fn x() {} | ||
| ^^^^^ expected identifier, found reserved keyword | ||
help: you can escape reserved keywords to use them as identifiers | ||
| | ||
LL | pub const r#async fn x() {} | ||
| ^^^^^^^ | ||
|
||
error: expected `:`, found keyword `fn` | ||
--> $DIR/no-const-async.rs:7:17 | ||
| | ||
LL | pub const async fn x() {} | ||
| ^^ expected `:` | ||
|
||
error: aborting due to 2 previous errors | ||
|