about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2019-06-25 10:55:32 -0400
committerNiko Matsakis <niko@alum.mit.edu>2019-07-02 12:25:23 -0400
commit5bd423a7ca5920e175a5d3eb8180dc24d9aa7cc4 (patch)
treedea2a791128af5839cfba3ebe53bd0fb5081117c
parent076b0d0f5cc33f108fda043c2e6e12229d734cf4 (diff)
downloadrust-5bd423a7ca5920e175a5d3eb8180dc24d9aa7cc4.tar.gz
rust-5bd423a7ca5920e175a5d3eb8180dc24d9aa7cc4.zip
introduce more tests covering `async fn` surface
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/elided.rs12
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs14
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/hrtb.rs (renamed from src/test/ui/async-await/async-fn-multiple-lifetimes.rs)5
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/named.rs12
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/partial-relation.rs15
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs18
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs18
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr10
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs27
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr11
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-ref.rs46
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr37
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/variance.rs18
13 files changed, 239 insertions, 4 deletions
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 00000000000..8355a450ae6
--- /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 00000000000..5f3820b6c31
--- /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
index c1202bfe219..620b0080966 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 00000000000..7d13d48bc8b
--- /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 00000000000..903c43950a5
--- /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 00000000000..08622311f7b
--- /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<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);
+}
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 00000000000..0359d5deb4d
--- /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<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);
+}
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 00000000000..de2c85d772a
--- /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 00000000000..27f789e340d
--- /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<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() {
+}
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 00000000000..f6d611517bc
--- /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 00000000000..98da90161e5
--- /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 00000000000..fe70d35942c
--- /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 00000000000..4c178871214
--- /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);
+}