Skip to content

Commit fbc7bbf

Browse files
authored
Rollup merge of rust-lang#63383 - Centril:async-lifetime-elision-tests, r=nikomatsakis
`async fn` lifetime elision tests Add `async fn` version of the tests in rust-lang#61207 per the first checkbox in rust-lang#62121 (comment). Works towards resolving blockers in rust-lang#63209. r? @nikomatsakis cc @cramertj
2 parents 9834518 + 5ce8f7a commit fbc7bbf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2867
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// check-pass
2+
// edition:2018
3+
4+
#![feature(async_await)]
5+
6+
use std::pin::Pin;
7+
use std::task::{Context, Poll};
8+
9+
struct Foo;
10+
11+
impl Foo {
12+
async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self }
13+
14+
async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self }
15+
16+
async fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self }
17+
18+
async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self }
19+
20+
fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self }
21+
}
22+
23+
type Alias<T> = Pin<T>;
24+
impl Foo {
25+
async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self }
26+
}
27+
28+
// FIXME(Centril): extend with the rest of the non-`async fn` test
29+
// when we allow `async fn`s inside traits and trait implementations.
30+
31+
fn main() {
32+
let mut foo = Foo;
33+
{ Pin::new(&foo).pin_ref() };
34+
{ Pin::new(&mut foo).pin_mut() };
35+
{ Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() };
36+
{ Pin::new(&foo).pin_ref_impl_trait() };
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:48
3+
|
4+
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
5+
| - ^^^^^^^^ returning this value requires that `'_` must outlive `'static`
6+
| |
7+
| lifetime `'_` defined here
8+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint
9+
|
10+
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
11+
| ^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition:2018
2+
3+
#![feature(async_await)]
4+
5+
use std::pin::Pin;
6+
7+
struct Foo;
8+
9+
impl Foo {
10+
async fn f(self: Pin<&Self>) -> impl Clone { self }
11+
//~^ ERROR cannot infer an appropriate lifetime
12+
}
13+
14+
fn main() {
15+
{ Pin::new(&Foo).f() };
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: cannot infer an appropriate lifetime
2+
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:16
3+
|
4+
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
5+
| ^^^^ ---------- this return type evaluates to the `'static` lifetime...
6+
| |
7+
| ...but this borrow...
8+
|
9+
note: ...can't outlive the lifetime '_ as defined on the method body at 10:26
10+
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:26
11+
|
12+
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
13+
| ^
14+
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 10:26
15+
|
16+
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
17+
| ^^^^^^^^^^^^^^^
18+
19+
error: aborting due to previous error
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:45
3+
|
4+
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
5+
| ^
6+
|
7+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
8+
9+
error[E0106]: missing lifetime specifier
10+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:60
11+
|
12+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
13+
| ^
14+
|
15+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
16+
17+
error[E0106]: missing lifetime specifier
18+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:67
19+
|
20+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
21+
| ^
22+
|
23+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
24+
25+
error: aborting due to 3 previous errors
26+
27+
For more information about this error, try `rustc --explain E0106`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// edition:2018
2+
3+
#![feature(async_await)]
4+
5+
use std::pin::Pin;
6+
7+
struct Foo;
8+
9+
impl Foo {
10+
async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
11+
//~^ ERROR missing lifetime specifier
12+
//~| ERROR cannot infer an appropriate lifetime
13+
// FIXME: should be E0623?
14+
15+
async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
16+
//~^ ERROR missing lifetime specifier
17+
//~| ERROR cannot infer an appropriate lifetime
18+
//~| ERROR missing lifetime specifier
19+
//~| ERROR cannot infer an appropriate lifetime
20+
// FIXME: should be E0623?
21+
}
22+
23+
type Alias<T> = Pin<T>;
24+
impl Foo {
25+
async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:45
3+
|
4+
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
5+
| ^
6+
|
7+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
8+
9+
error[E0106]: missing lifetime specifier
10+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:60
11+
|
12+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
13+
| ^
14+
|
15+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
16+
17+
error[E0106]: missing lifetime specifier
18+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:67
19+
|
20+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
21+
| ^
22+
|
23+
= note: return-position elided lifetimes require exactly one input-position elided lifetime, found multiple.
24+
25+
error: cannot infer an appropriate lifetime
26+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:33
27+
|
28+
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
29+
| ^ ---- this return type evaluates to the `'static` lifetime...
30+
| |
31+
| ...but this borrow...
32+
|
33+
note: ...can't outlive the lifetime '_ as defined on the method body at 10:26
34+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:26
35+
|
36+
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
37+
| ^
38+
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 10:26
39+
|
40+
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo + '_ { f }
41+
| ^^^^^^^^^
42+
43+
error: cannot infer an appropriate lifetime
44+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:16
45+
|
46+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
47+
| ^^^^ ...but this borrow... ----------------- this return type evaluates to the `'static` lifetime...
48+
|
49+
note: ...can't outlive the lifetime '_ as defined on the method body at 15:26
50+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:26
51+
|
52+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
53+
| ^
54+
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 15:26
55+
|
56+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) + '_ { (self, f) }
57+
| ^^^^^^^^^^^^^^^^^^^^^^
58+
59+
error: cannot infer an appropriate lifetime
60+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:34
61+
|
62+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
63+
| ^ ----------------- this return type evaluates to the `'static` lifetime...
64+
| |
65+
| ...but this borrow...
66+
|
67+
note: ...can't outlive the lifetime '_ as defined on the method body at 15:26
68+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:26
69+
|
70+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
71+
| ^
72+
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 15:26
73+
|
74+
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) + '_ { (self, f) }
75+
| ^^^^^^^^^^^^^^^^^^^^^^
76+
77+
error[E0623]: lifetime mismatch
78+
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:25:58
79+
|
80+
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
81+
| ----- ^^^
82+
| | |
83+
| | ...but data from `arg` is returned here
84+
| this parameter and the return type are declared with different lifetimes...
85+
86+
error: aborting due to 7 previous errors
87+
88+
For more information about this error, try `rustc --explain E0106`.

src/test/ui/self/elision/README.md

+31
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,34 @@ In each case, we test the following patterns:
4242
- `self: Box<Pin<XXX>>`
4343

4444
In the non-reference cases, `Pin` causes errors so we substitute `Rc`.
45+
46+
### `async fn`
47+
48+
For each of the tests above we also check that `async fn` behaves as an `fn` would.
49+
These tests are in files named `*-async.rs`.
50+
51+
Legends:
52+
- ✓ ⟹ Yes / Pass
53+
- X ⟹ No
54+
- α ⟹ lifetime mismatch
55+
- β ⟹ cannot infer an appropriate lifetime
56+
- γ ⟹ missing lifetime specifier
57+
58+
| `async` file | Pass? | Conforms to `fn`? | How does it diverge? <br/> `fn``async fn` |
59+
| --- | --- | --- | --- |
60+
| `self-async.rs` ||| N/A |
61+
| `struct-async.rs`||| N/A |
62+
| `alias-async.rs`||| N/A |
63+
| `assoc-async.rs`||| N/A |
64+
| `ref-self-async.rs` | X | X | α ⟶ β + γ |
65+
| `ref-mut-self-async.rs` | X | X | α ⟶ β + γ |
66+
| `ref-struct-async.rs` | X | X | α ⟶ β + γ |
67+
| `ref-mut-struct-async.rs` | X | X | α ⟶ β + γ |
68+
| `ref-alias-async.rs` | X | X | ✓ ⟶ β + γ |
69+
| `ref-assoc-async.rs` | X | X | ✓ ⟶ β + γ |
70+
| `ref-mut-alias-async.rs` | X | X | ✓ ⟶ β + γ |
71+
| `lt-self-async.rs` | ✓ | ✓ | N/A
72+
| `lt-struct-async.rs` | ✓ | ✓ | N/A
73+
| `lt-alias-async.rs` | ✓ | ✓ | N/A
74+
| `lt-assoc-async.rs` | ✓ | ✓ | N/A
75+
| `lt-ref-self-async.rs` | X | X | α ⟶ β + γ
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
// edition:2018
3+
4+
#![feature(async_await)]
5+
6+
#![feature(arbitrary_self_types)]
7+
#![allow(non_snake_case)]
8+
9+
use std::rc::Rc;
10+
11+
struct Struct { }
12+
13+
type Alias = Struct;
14+
15+
impl Struct {
16+
// Test using an alias for `Struct`:
17+
18+
async fn alias(self: Alias, f: &u32) -> &u32 {
19+
f
20+
}
21+
22+
async fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 {
23+
f
24+
}
25+
26+
async fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 {
27+
f
28+
}
29+
30+
async fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 {
31+
f
32+
}
33+
34+
async fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 {
35+
f
36+
}
37+
}
38+
39+
fn main() { }
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// check-pass
2+
// edition:2018
3+
4+
#![feature(async_await)]
5+
6+
#![feature(arbitrary_self_types)]
7+
#![allow(non_snake_case)]
8+
9+
use std::rc::Rc;
10+
11+
trait Trait {
12+
type AssocType;
13+
}
14+
15+
struct Struct { }
16+
17+
impl Trait for Struct {
18+
type AssocType = Self;
19+
}
20+
21+
impl Struct {
22+
async fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 {
23+
f
24+
}
25+
26+
async fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
27+
f
28+
}
29+
30+
async fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
31+
f
32+
}
33+
34+
async fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
35+
f
36+
}
37+
38+
async fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
39+
f
40+
}
41+
}
42+
43+
fn main() { }
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// check-pass
2+
// edition:2018
3+
4+
#![feature(async_await)]
5+
6+
#![feature(arbitrary_self_types)]
7+
#![allow(non_snake_case)]
8+
9+
use std::rc::Rc;
10+
11+
struct Struct<'a> { x: &'a u32 }
12+
13+
type Alias<'a> = Struct<'a>;
14+
15+
impl<'a> Alias<'a> {
16+
async fn take_self(self, f: &u32) -> &u32 {
17+
f
18+
}
19+
20+
async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 {
21+
f
22+
}
23+
24+
async fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 {
25+
f
26+
}
27+
28+
async fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 {
29+
f
30+
}
31+
32+
async fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 {
33+
f
34+
}
35+
36+
async fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 {
37+
f
38+
}
39+
}
40+
41+
fn main() { }

0 commit comments

Comments
 (0)