Rollup merge of #76468 - SNCPlay42:lifetime-names, r=Mark-Simulacrum
Improve lifetime name annotations for closures & async functions * Don't refer to async functions as "generators" in error output * Where possible, emit annotations pointing exactly at the `&` in the return type of closures (when they have explicit return types) and async functions, like we do for arguments. Addresses #74072, but I wouldn't call that *closed* until annotations are identical for async and non-async functions. * Emit a better annotation when the lifetime doesn't appear in the full name type, which currently happens for opaque types like `impl Future`. Addresses #74497, but further improves could probably be made (why *doesn't* it appear in the type as `impl Future + '1`?) This is included in the same PR because the changes to `give_name_if_anonymous_region_appears_in_output` would introduce ICE otherwise (it would return `None` in cases where it didn't previously, which then gets `unwrap`ped)
This commit is contained in:
commit
99f16e637b
7 changed files with 282 additions and 46 deletions
|
|
@ -0,0 +1,37 @@
|
|||
// edition:2018
|
||||
#![feature(async_closure)]
|
||||
use std::future::Future;
|
||||
|
||||
// test the quality of annotations giving lifetimes names (`'1`) when async constructs are involved
|
||||
|
||||
pub async fn async_fn(x: &mut i32) -> &i32 {
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
}
|
||||
|
||||
pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
(async move || {
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
})()
|
||||
}
|
||||
|
||||
pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
(async move || -> &i32 {
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
})()
|
||||
}
|
||||
|
||||
pub fn async_block(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
async move {
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:9:5
|
||||
|
|
||||
LL | pub async fn async_fn(x: &mut i32) -> &i32 {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | let y = &*x;
|
||||
| --- borrow of `*x` occurs here
|
||||
LL | *x += 1;
|
||||
| ^^^^^^^ assignment to borrowed `*x` occurs here
|
||||
LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:16:9
|
||||
|
|
||||
LL | let y = &*x;
|
||||
| --- borrow of `*x` occurs here
|
||||
LL | *x += 1;
|
||||
| ^^^^^^^ assignment to borrowed `*x` occurs here
|
||||
LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
LL | })()
|
||||
| - return type of async closure is &'1 i32
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:24:9
|
||||
|
|
||||
LL | (async move || -> &i32 {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | let y = &*x;
|
||||
| --- borrow of `*x` occurs here
|
||||
LL | *x += 1;
|
||||
| ^^^^^^^ assignment to borrowed `*x` occurs here
|
||||
LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:32:9
|
||||
|
|
||||
LL | let y = &*x;
|
||||
| --- borrow of `*x` occurs here
|
||||
LL | *x += 1;
|
||||
| ^^^^^^^ assignment to borrowed `*x` occurs here
|
||||
LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
LL | }
|
||||
| - return type of async block is &'1 i32
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0506`.
|
||||
19
src/test/ui/async-await/issue-74497-lifetime-in-opaque.rs
Normal file
19
src/test/ui/async-await/issue-74497-lifetime-in-opaque.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// edition:2018
|
||||
|
||||
// test that names give to anonymous lifetimes in opaque types like `impl Future` are correctly
|
||||
// introduced in error messages
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
pub async fn foo<F, T>(_: F)
|
||||
where
|
||||
F: Fn(&u8) -> T,
|
||||
T: Future<Output = ()>,
|
||||
{
|
||||
}
|
||||
|
||||
pub async fn bar(_: &u8) {}
|
||||
|
||||
fn main() {
|
||||
let _ = foo(|x| bar(x)); //~ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/issue-74497-lifetime-in-opaque.rs:18:21
|
||||
|
|
||||
LL | let _ = foo(|x| bar(x));
|
||||
| -- ^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||
| ||
|
||||
| |return type of closure `impl Future` contains a lifetime `'2`
|
||||
| has type `&'1 u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ error: lifetime may not live long enough
|
|||
LL | let _action = move || {
|
||||
| -------
|
||||
| | |
|
||||
| | return type of closure is [closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:15]
|
||||
| | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:15]` contains a lifetime `'2`
|
||||
| lifetime `'1` represents this closure's body
|
||||
LL | || f() // The `nested` closure
|
||||
| ^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ error: lifetime may not live long enough
|
|||
--> $DIR/issue-58053.rs:6:33
|
||||
|
|
||||
LL | let f = |x: &i32| -> &i32 { x };
|
||||
| - ---- ^ returning this value requires that `'1` must outlive `'2`
|
||||
| - - ^ returning this value requires that `'1` must outlive `'2`
|
||||
| | |
|
||||
| | return type of closure is &'2 i32
|
||||
| | let's call the lifetime of this reference `'2`
|
||||
| let's call the lifetime of this reference `'1`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue