Rustのライフタイムをエラーから逆算する

# はじめに
Rustのコンパイラ頭良いので、良い感じにアドバイスくれてそれ通りに実装すればエラーは消えるんですけど、そもそもそもなんでエラー出てるのかとか、ライフタイム全然理解してない状態なので逆算で調べていきます。

結論から言うと完全には理解できなかったので、理解した時に更新していきます。

コード自体は抜粋なので、エラーメッセージの行数と合わないですが気にしないでください。

# 実装
以下のようなHashMapを使ったstructを作ったらエラー出ました。

```rust
use std::collections::HashMap;

pub struct Sample {
    hm: HashMap<u32, Vec<&str>>,
}

impl Sample {
    pub fn new() -> Sample {
        Self {
            hm: HashMap::new(),
        }
    }
}

// 20 |  hm: HashMap<u32, Vec<&str>>,
//    |                       ^ expected named lifetime parameter
//    |
// help: consider introducing a named lifetime parameter
//    |
// 19 ~ pub struct Sample<'a> {
// 20 ~     hm: HashMap<u32, Vec<&'a str>>,
```
これは`Vec<&str>`の部分で色々な参照が入るから、同じライフタイムを持っていることを保証しないっていうことっぽいです。
なので、以下のように書き換えます。

```rust
use std::collections::HashMap;

pub struct Sample<'a> {
    hm: HashMap<u32, Vec<&'a str>>,
}

impl Sample {
    pub fn new() -> Sample {
        Self {
            hm: HashMap::new(),
        }
    }
}
```

これで、`Vec<&'a str>`部分は同じライフタイム'aを持つことになりました。
しかし、以下のようなエラーが出ます。

```rust
// error[E0726]: implicit elided lifetime not allowed here
//   --> Main.rs:21:6
//    |
// 21 | impl Sample {
//    |      ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
//    |
//    = note: assuming a `'static` lifetime...

// error[E0106]: missing lifetime specifier
//   --> Main.rs:22:21
//    |
// 22 |     pub fn new() -> Sample {
//    |                     ^^^^^^ expected named lifetime parameter
//    |
//    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
// help: consider using the `'static` lifetime
//    |
// 22 |     pub fn new() -> Sample<'static> {
//    |                     ~~~~~~~~~~~~~~~

// error: aborting due to 2 previous errors
```

上から読み解くと、

> help: indicate the anonymous lifetime: \`<'_>\`

匿名ライフタイム使ってくださいってことらしいんですが、匿名ライフタイムよくわかってないのですが、要はある条件下においてライフタイムの記述を省略できるのですが、その時に使うっぽいです。（[こちらの記事](https://zenn.dev/takanori_is/articles/anonymous-lifetime-the-lifetime-we-saw-that-day)を参考にさせてもらいました）

> note: assuming a \`'static\` lifetime...

って書いてあるので、まあでも多分'staticなんでしょうとコンパイラは認識してるっぽいですね。
そのため、以下のに書けと書いてあります。

> pub fn new() -> Sample<'static>

これを踏まえて書き換えると、

```rust
use std::collections::HashMap;

pub struct Sample<'a> {
    hm: HashMap<u32, Vec<&'a str>>,
}

impl Sample<'_> {
    pub fn new() -> Sample<'static> {
        Self {
            hm: HashMap::new(),
        }
    }
}
```

こうすると以下のようなエラーになります。


```rust
// error[E0308]: mismatched types
//   --> Main.rs:25:9
//    |
// 25 | /         Self {
// 26 | |             hm: HashMap::new(),
// 27 | |         }
//    | |_________^ lifetime mismatch
//    |
//    = note: expected struct `Sample<'static>`
//               found struct `Sample<'_>`
// note: the lifetime `'_` as defined here...
//   --> Main.rs:23:13
//    |
// 23 | impl Sample<'_> {
//    |             ^^
//    = note: ...does not necessarily outlive the static lifetime
```

なんか型が違うようって言われてますね。<'_>と<'static>じゃ違うってことですね。なんかstaticだと思うけどみたいなエラーメッセージ出てたのはなんだったのかは分かりませんが、Sample<'static>と書けってことらしいので、以下のようにしたらエラーは消えました。

```rust
use std::collections::HashMap;

pub struct Sample<'a> {
    hm: HashMap<u32, Vec<&'a str>>,
}

impl Sample<'static> {
    pub fn new() -> Sample<'static> {
        Self {
            hm: HashMap::new(),
        }
    }
}
```

なんかよくわからないことたくさんなので、気づいたら追記していきます。