diff --git a/src/test/ui/async-await/multiple-lifetimes/elided.rs b/src/test/ui/async-await/multiple-lifetimes/elided.rs new file mode 100644 index 0000000000000..8355a450ae641 --- /dev/null +++ b/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); +} diff --git a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs new file mode 100644 index 0000000000000..5f3820b6c31cd --- /dev/null +++ b/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); +} diff --git a/src/test/ui/async-await/async-fn-multiple-lifetimes.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs similarity index 73% rename from src/test/ui/async-await/async-fn-multiple-lifetimes.rs rename to src/test/ui/async-await/multiple-lifetimes/hrtb.rs index c1202bfe21992..620b0080966b9 100644 --- a/src/test/ui/async-await/async-fn-multiple-lifetimes.rs +++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs @@ -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() {} diff --git a/src/test/ui/async-await/multiple-lifetimes/named.rs b/src/test/ui/async-await/multiple-lifetimes/named.rs new file mode 100644 index 0000000000000..7d13d48bc8bbd --- /dev/null +++ b/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); +} diff --git a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs new file mode 100644 index 0000000000000..903c43950a5c4 --- /dev/null +++ b/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); +} diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs new file mode 100644 index 0000000000000..08622311f7b1c --- /dev/null +++ b/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 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); +} diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs new file mode 100644 index 0000000000000..0359d5deb4d30 --- /dev/null +++ b/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 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); +} diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr new file mode 100644 index 0000000000000..de2c85d772a72 --- /dev/null +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr @@ -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 + diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs new file mode 100644 index 0000000000000..27f789e340d09 --- /dev/null +++ b/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 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() { +} diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr new file mode 100644 index 0000000000000..f6d611517bc8f --- /dev/null +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -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 + diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs new file mode 100644 index 0000000000000..98da90161e5fd --- /dev/null +++ b/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() { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr new file mode 100644 index 0000000000000..fe70d35942c7c --- /dev/null +++ b/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`. diff --git a/src/test/ui/async-await/multiple-lifetimes/variance.rs b/src/test/ui/async-await/multiple-lifetimes/variance.rs new file mode 100644 index 0000000000000..4c1788712148b --- /dev/null +++ b/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); +}