Skip to content

Explain elision when it is relevant to lifetime errors #74597

Open
@SNCPlay42

Description

@SNCPlay42
#![feature(nll)]

fn mutate_while_borrowed(x: &mut i32) -> &i32 {
    let y = &*x;
    *x += 1;
    y
}

struct S;
impl S {
    fn wrong_elided_lifetime(&self, x: &i32) -> &i32 {
        x
    }
}

Gives these errors

error[E0506]: cannot assign to `*x` because it is borrowed
 --> src/lib.rs:5:5
  |
3 | fn mutate_while_borrowed(x: &mut i32) -> &i32 {
  |                             - let's call the lifetime of this reference `'1`
4 |     let y = &*x;
  |             --- borrow of `*x` occurs here
5 |     *x += 1;
  |     ^^^^^^^ assignment to borrowed `*x` occurs here
6 |     y
  |     - returning this value requires that `*x` is borrowed for `'1`

error: lifetime may not live long enough
  --> src/lib.rs:12:9
   |
11 |     fn wrong_elided_lifetime(&self, x: &i32) -> &i32 {
   |                              -         - let's call the lifetime of this reference `'1`
   |                              |
   |                              let's call the lifetime of this reference `'2`
12 |         x
   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error: aborting due to 2 previous errors

It's not made clear why the returns are expected to have lifetime '1. It would be helpful to have annotations like

3 | fn mutate_while_borrowed(x: &mut i32) -> &i32 {
  |                             -            - this elided lifetime is inferred to be `'1`
  |                             |
  |                             let's call the lifetime of this reference `'1`

Maybe link to the book section as well? For the second function, maybe adding a named lifetime (f<'a>(&self, &'a i32) -> &'a i32) could be automatically suggested, but that does change the semantics of the function to callers.

Without #![feature(nll)], the second function produces a different error, which could also use these enhancements:

error[E0623]: lifetime mismatch
  --> src/lib.rs:10:9
   |
9  |     fn wrong_elided_lifetime(&self, x: &i32) -> &i32 {
   |                                        ----     ----
   |                                        |
   |                                        this parameter and the return type are declared with different lifetimes...
10 |         x
   |         ^ ...but data from `x` is returned here

@rustbot modify labels: +C-enhancement +A-diagnostics +A-lifetimes

@rustbot claim

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions