Repository: rust
Issue: confusing error message saying variable must be valid for anonymous lifetime that it appears to live long enough for
Labels: C-enhancement,A-diagnostics,A-lifetimes,T-compiler

I initially [raised this on twitter](https://twitter.com/davidbaron/status/856772994294788097) without a reduced testcase, and @SimonSapin [suggested I file an issue](https://twitter.com/SimonSapin/status/856795953851805696) because the error message could be improved.

A reasonably-reduced testcase for this error is the following code:

```rust
pub struct IrcServer {
    options: String,
}

impl IrcServer {
    fn new() -> IrcServer {
        IrcServer { options: String::from("test") }
    }

    fn options(&self) -> &String {
        &self.options
    }
}

pub fn main_loop_iteration(server: IrcServer, irc_state: &mut IRCState) {
    let options = server.options();
    handle_bot_command(&server, options, irc_state)
}

fn handle_bot_command<'opts>(server: &IrcServer,
                             options: &'opts String,
                             irc_state: &mut IRCState<'opts>) {
}

pub struct IRCState<'opts> {
    options: &'opts String,
}

impl<'opts> IRCState<'opts> {
    fn new(options_: &'opts String) -> IRCState<'opts> {
        IRCState { options: options_ }
    }
}
```

which, when compiled with `rustc --crate-type lib lib.rs` gives the following error:

```
error: `server` does not live long enough
  --> lib.rs:16:19
   |
16 |     let options = server.options();
   |                   ^^^^^^ does not live long enough
17 |     handle_bot_command(&server, options, irc_state)
18 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #2 defined on the body at 15:72...
  --> lib.rs:15:73
   |
15 |   pub fn main_loop_iteration(server: IrcServer, irc_state: &mut IRCState) {
   |  _________________________________________________________________________^ starting here...
16 | |     let options = server.options();
17 | |     handle_bot_command(&server, options, irc_state)
18 | | }
   | |_^ ...ending here

error: aborting due to previous error
```

This error is particularly confusing because it looks like the borrowed value *is* valid for the anonymous lifetime being pointed to; the "borrowed value only lives until here" points to the same point as the "...ending here".

The way to fix the code is with lifetime parameters and passing `options` in from the caller, i.e., to change the code to be:

```rust
pub struct IrcServer {
    options: String,
}

impl IrcServer {
    fn new() -> IrcServer {
        IrcServer { options: String::from("test") }
    }

    fn options(&self) -> &String {
        &self.options
    }
}

pub fn main_loop_iteration<'opts>(server: IrcServer,
                                  options: &'opts String,
                                  irc_state: &mut IRCState<'opts>) {
    handle_bot_command(&server, options, irc_state)
}

fn handle_bot_command<'opts>(server: &IrcServer,
                             options: &'opts String,
                             irc_state: &mut IRCState<'opts>) {
}

pub struct IRCState<'opts> {
    options: &'opts String,
}

impl<'opts> IRCState<'opts> {
    fn new(options_: &'opts String) -> IRCState<'opts> {
        IRCState { options: options_ }
    }
}
```

but it required stepping away from the problem for a bit and coming back to it later to recognize that.