Rust: Lifetime elision is too greedy without explicit type declaration

Created on 19 Feb 2017  路  3Comments  路  Source: rust-lang/rust

In the next example the closure borrows the value for longer than it should do:

fn main () {
    let f = |y| { println!("{}", y); };
    let x = 4u8;
    f(&x);
}

Which causes compilation error:

error: `x` does not live long enough
 --> ./test.rs:5:1
  |
4 |     f(&x);
  |        - borrow occurs here
5 | }
  | ^ `x` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

However, if we declare the argument type explicitly, it works just as expected:

fn main () {
    let f = |y: &u8| { println!("{}", y); };
    let x = 4u8;
    f(&x);
}

Not sure if that is a bug or expected behaviour. Neither could I find explanation of this effect in the documentation.

Meta

rustc --version --verbose:

rustc 1.17.0-nightly (24a70eb59 2017-02-09)
binary: rustc
commit-hash: 24a70eb598a76edb0941f628a87946b40f2a1c83
commit-date: 2017-02-09
host: x86_64-unknown-linux-gnu
release: 1.17.0-nightly
LLVM version: 3.9
A-closures A-inference A-lifetimes C-bug NLL-fixed-by-NLL T-compiler

Most helpful comment

Triage: now compiles on 2018.
2015 errors:

error[E0597]: `x` does not live long enough
 --> src/main.rs:4:8
  |
4 |     f(&x);
  |        ^ borrowed value does not live long enough
5 | }
  | - `x` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

rustc: 1.32.0

All 3 comments

Just to drop a term for search engines: exploring this today on the users forum, I got the strong impression that the reason |x: &u8| works may be related to it serving as a hint for HRTB.

Possibly related: I ran into this one as well (specifically huon's october example), which oddly enough breaks in the other direction; that is, it only works _without_ the explicit annotation: https://github.com/rust-lang/rust/issues/22557

Triage: now compiles on 2018.
2015 errors:

error[E0597]: `x` does not live long enough
 --> src/main.rs:4:8
  |
4 |     f(&x);
  |        ^ borrowed value does not live long enough
5 | }
  | - `x` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

rustc: 1.32.0

Closing since this is no longer a problem on nightly in either edition

Was this page helpful?
0 / 5 - 0 ratings