Skip to content

Commit

Permalink
introduce more tests covering async fn surface
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Jul 2, 2019
1 parent 076b0d0 commit 5bd423a
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 4 deletions.
12 changes: 12 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/elided.rs
@@ -0,0 +1,12 @@
// edition:2018
// run-pass

// Test that we can use async fns with multiple arbitrary lifetimes.

#![feature(async_await, await_macro)]

async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}

fn main() {
let _ = multiple_elided_lifetimes(&22, &44);
}
14 changes: 14 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs
@@ -0,0 +1,14 @@
// edition:2018
// run-pass

// Test that we can use async fns with multiple arbitrary lifetimes.

#![feature(arbitrary_self_types, async_await, await_macro)]

async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {}

fn gimme(_: &u8) { }

fn main() {
let _ = multiple_named_lifetimes(&22, &44, gimme);
}
Expand Up @@ -4,17 +4,14 @@
// Test that we can use async fns with multiple arbitrary lifetimes.

#![feature(arbitrary_self_types, async_await, await_macro)]
#![allow(dead_code)]

use std::ops::Add;

async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}

async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
_: impl for<'a> Add<&'a u8>,
_: impl for<'b> Add<&'b u8>,
_: &'c u8,
) {}

async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/named.rs
@@ -0,0 +1,12 @@
// edition:2018
// run-pass

// Test that we can use async fns with multiple arbitrary lifetimes.

#![feature(arbitrary_self_types, async_await, await_macro)]

async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}

fn main() {
let _ = multiple_named_lifetimes(&22, &44);
}
15 changes: 15 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/partial-relation.rs
@@ -0,0 +1,15 @@
// edition:2018
// run-pass

#![feature(async_await)]

async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
where 'b: 'a
{
drop((a, c));
(b, b)
}

fn main() {
let _ = lotsa_lifetimes(&22, &44, &66);
}
18 changes: 18 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs
@@ -0,0 +1,18 @@
// edition:2018
// run-pass

// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.

#![feature(async_await, member_constraints)]

trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }

async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
(a, b)
}

fn main() {
let _ = async_ret_impl_trait(&22, &44);
}
18 changes: 18 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
@@ -0,0 +1,18 @@
// edition:2018

// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.

#![feature(arbitrary_self_types, async_await, await_macro)]

trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }

async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
//~^ ERROR ambiguous lifetime bound
(a, b)
}

fn main() {
let _ = async_ret_impl_trait(&22, &44);
}
@@ -0,0 +1,10 @@
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/ret-impl-trait-no-fg.rs:11:64
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
= help: add #![feature(member_constraints)] to the crate attributes to enable

error: aborting due to previous error

27 changes: 27 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs
@@ -0,0 +1,27 @@
// edition:2018

// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.

#![feature(async_await, member_constraints)]

trait Trait<'a> { }
impl<T> Trait<'_> for T { }

// Only `'a` permitted in return type, not `'b`.
async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
//~^ ERROR lifetime mismatch
(a, b)
}

// As above, but `'b: 'a`, so return type ca be inferred to `(&'a u8,
// &'a u8)`.
async fn async_ret_impl_trait2<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a>
where
'b: 'a,
{
(a, b)
}

fn main() {
}
@@ -0,0 +1,11 @@
error[E0623]: lifetime mismatch
--> $DIR/ret-impl-trait-one.rs:12:65
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
| ------ ^^^^^^^^^^^^^^
| | |
| | ...but data from `b` is returned here
| this parameter and the return type are declared with different lifetimes...

error: aborting due to previous error

46 changes: 46 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/ret-ref.rs
@@ -0,0 +1,46 @@
// edition:2018

// Test that we get the expected borrow check errors when an async
// function (which takes multiple lifetimes) only returns data from
// one of them.

#![feature(async_await)]

async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 {
a
}

// Both are borrowed whilst the future is live.
async fn future_live() {
let mut a = 22;
let mut b = 44;
let future = multiple_named_lifetimes(&a, &b);
a += 1; //~ ERROR cannot assign
b += 1; //~ ERROR cannot assign
let p = future.await;
drop(p);
}

// Just the return value is live after future is awaited.
async fn just_return_live() {
let mut a = 22;
let mut b = 44;
let future = multiple_named_lifetimes(&a, &b);
let p = future.await;
a += 1; //~ ERROR cannot assign
b += 1;
drop(p);
}

// Once `p` is dead, both `a` and `b` are unborrowed.
async fn after_both_dead() {
let mut a = 22;
let mut b = 44;
let future = multiple_named_lifetimes(&a, &b);
let p = future.await;
drop(p);
a += 1;
b += 1;
}

fn main() { }
37 changes: 37 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr
@@ -0,0 +1,37 @@
error[E0506]: cannot assign to `a` because it is borrowed
--> $DIR/ret-ref.rs:18:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
| -- borrow of `a` occurs here
LL | a += 1;
| ^^^^^^ assignment to borrowed `a` occurs here
LL | b += 1;
LL | let p = future.await;
| ------ borrow later used here

error[E0506]: cannot assign to `b` because it is borrowed
--> $DIR/ret-ref.rs:19:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
| -- borrow of `b` occurs here
LL | a += 1;
LL | b += 1;
| ^^^^^^ assignment to borrowed `b` occurs here
LL | let p = future.await;
| ------ borrow later used here

error[E0506]: cannot assign to `a` because it is borrowed
--> $DIR/ret-ref.rs:30:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
| -- borrow of `a` occurs here
LL | let p = future.await;
LL | a += 1;
| ^^^^^^ assignment to borrowed `a` occurs here
LL | b += 1;
LL | drop(p);
| - borrow later used here

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0506`.
18 changes: 18 additions & 0 deletions src/test/ui/async-await/multiple-lifetimes/variance.rs
@@ -0,0 +1,18 @@
// edition:2018
// run-pass

// Test for async fn where the parameters have distinct lifetime
// parameters that appear in all possible variances.

#![feature(arbitrary_self_types, async_await, await_macro)]

#[allow(dead_code)]
async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { }

fn take_any(_: &u8) { }
fn identify(x: &u8) -> &u8 { x }
fn give_back() -> &'static u8 { &22 }

fn main() {
let _ = lotsa_lifetimes(take_any, identify, give_back);
}

0 comments on commit 5bd423a

Please sign in to comment.