Rustコンパイラに叱られる！

# お題
Rustビギナーは必ずハマるという「借用チェッカとの戦い」の記録。
随時、更新予定。
まずは、自分が簡単なツールを作成しようとした時↓に遭遇したものから挙げていく。
・[簡単なツール作成を通してRustを学ぶ](https://qiita.com/sky0621/items/86d9159bc1930618162c)
・[【改善編】簡単なツール作成を通してRustを学ぶ](https://qiita.com/sky0621/items/a70cc7a9453795e0c9e9)
Rustのエラーページに書かれたものを網羅（それならそもそもそのページ見ればいい話）するより、
実際に何かしらツール作りをする過程で遭遇するものを挙げていった方が参考になるのでは？（作るツールやらアプリやらの特性によっても遭遇するエラーは変わるかもしれないけど）

ちなみに、単に、こう書くと「叱られる」という事実と、こう書くと回避（よい回避方法かまでは未検証）できるという事実だけを列挙。
なにしろ自分もRustはじめて数週間なので、間違っているかもしれない理屈をだらだら書くよりは実際に動かして起きた事実のみを列挙した方がよいかと。

## 編集履歴
2020-09-20 「E0038」と「E0277」についてコメントもらったので修正

# 対象者
Rustの勉強はじめてチュートリアルを写経くらいはしたけど、実際に自分で書き始めたらRustコンパイラにいろいろ叱られ始めた人。

# 実装・動作確認端末
### # OS - Linux
```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
```

### # 言語バージョン
```
$ rustc --version
rustc 1.46.0 (04488afe3 2020-08-24)
$
$ cargo --version
cargo 1.46.0 (149022b1d 2020-07-17)
```

### # IDE - IntelliJ IDEA
```
IntelliJ IDEA 2020.2.1 (Ultimate Edition)
Build #IU-202.6948.69, built on August 25, 2020
```

# 実践

## [E0382] よそに渡した変数は、もう使えないよ。
たぶん一番ベタなやつ。
Rust以外の言語やってて、ここで怒られたことないから、（聞いてはいたけど）初見でビックリする。

### ソース
```rust:main.rs
fn main() {
    let name = String::from("taro");
    println!("{}", name);

    let u = User { name };
    println!("{}", u.name);

    println!("{}", name);    <--- 叱られる。
}

struct User {
    name: String,
}
```

### 事象
`name`が、最初は`println`できたのに、構造体`User`に渡したあとは`println`できない。
こんなふうに叱られる。

```
borrow of moved value: `name` E0382 value borrowed here after move
```

https://doc.rust-lang.org/error-index.html#E0382

### 回避策
```rust:main.rs
fn main() {
    let name = String::from("taro");
    println!("{}", name);

    let u = User { name: &name };
    println!("{}", u.name);

    println!("{}", name);
}

struct User<'a> {
    name: &'a String,  <--- 実体でなくて参照をもらう形にする。
}
```

## [E0004] パターンは網羅しないといけないよ。
これは、ちょろい。
（使ってるIDE（とプラグイン）によるかもだけど）「こうしたら？」って解決策を提示してくれるので従うだけで解決。

### ソース
```rust:main.rs
fn main() {
    let x = 1;
    match x {          <--- 叱られる。
        0 => println!("zero"),
        1 => println!("one"),
        2 => println!("two"),
    }
}
```

### 事象
パターンマッチは取りうる値を網羅して列挙しないといけないのです。
こんなふうに叱られる。

```
Match must be exhaustive [E0004]
```

https://doc.rust-lang.org/error-index.html#E0004

### 回避策
もちろん今回のケースで全数値を並べていくわけにはいかないので、「その他」すべての扱いなら「`_ => ~~`」でいいんです。

```rust:main.rs
fn main() {
    let x = 1;
    match x {
        0 => println!("zero"),
        1 => println!("one"),
        2 => println!("two"),
        _ => println!("other"),   <--- これ、ちゃんと補ってあげて。
    }
}
```

## [E0038] トレイトオブジェクトを使うときのルールに則ってないよ。
トレイトオブジェクトは、 指定したトレイトを実装するある型のインスタンスを指す。
以下のように、なんとなく「Javaのインターフェースみたいなもんでしょ？」という感じで使うと、叱られる。

### ソース
```rust:main.rs
fn main() {
    let g = Get {};
    exec(g);
}

trait Command {
    fn run();
}

struct Get {}

impl Command for Get {
    fn run() {
        println!("Get!");
    }
}

fn exec(cmd: Command) {   <--- 叱られる。
    cmd.run();
}
```

### 事象
こんなふうに叱られる。

```
the trait `Command` cannot be made into an object E0038 
Help: consider turning `run` into a method by giving it a `&self` 
argument or constraining it so it does not apply to trait objects
```

https://doc.rust-lang.org/error-index.html#E0038

### [2020-09-20 コメントもらったので修正] 回避策
今回のサンプル事例の書き方だと、Rustのコンパイラは「`トレイトオブジェクト`（ポリモーフィズムの中でも`動的ディスパッチ`をサポートするための機能）」でやろうとしていると判断する様子。
ただ、目的としては`Command`トレイトを実装する何かが渡せればいい、そして、プログラム中で渡す構造体は既に決まっている、ということで、実は「`トレイト境界`（`静的ディスパッチ`をサポートするための機能）」を使えばよかったらしい。

※このあたりの話は下記参照。（公式ドキュメントでは第２版を見るよう促されるけど、今回事例で言うと下記がわかりやすい。）
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/trait-objects.html


```rust:main.rs
fn main() {
    let g = Get {};
    exec(&g);
}

trait Command {
    fn run(&self);
}

struct Get {}

impl Command for Get {
    fn run(&self) {
        println!("Get!");
    }
}

fn exec<T: Command>(cmd: &T) {   <-- ジェネリクスにする。
    cmd.run();
}
```

## [E0277] トレイトじゃあ、サイズがわからないよ。

### ソース
```rust:main.rs
fn main() {
    let g = Get {};
    exec(g);
}

trait Command {
    fn run(&self);
}

struct Get {}

impl Command for Get {
    fn run(&self) {
        println!("Get!");
    }
}

fn exec(cmd: Command) {   <--- 叱られる。
    cmd.run();
}
```

### 事象
こんなふうに叱られる。

```
the trait bound `dyn Command: std::marker::Sized` is not satisfied [E0277] 
`dyn Command` does not have a constant size known at compile-time
```

トレイトだとコンパイル時にサイズがわからない（具体的に渡されるトレイトオブジェクト？がわからない）のがダメらしい。
↓を見ると、またニュアンスが違うんだけど・・・。

https://doc.rust-lang.org/error-index.html#E0277

### 回避策
IDEから提示される回避案は複数あった。

#### １つ目
`Box`で囲ってしまえと言われた。
Boxについては以下参照。
https://doc.rust-jp.rs/book/second-edition/ch15-01-box.html

```rust:main.rs
fn main() {
    let g = Box::new(Get {});   <--- 当然、渡す方も囲わないといけない。
    exec(g);
}

trait Command {
    fn run(&self);
}

struct Get {}

impl Command for Get {
    fn run(&self) {
        println!("Get!");
    }
}

fn exec(cmd: Box<Command>) {   <--- はい、この通り。
    cmd.run();
}
```

#### ２つ目
参照にしちゃえと言われた。
`mut`が必要ないなら、こちらの方が楽かな。

```rust:main.rs
fn main() {
    let g = Get {};
    exec(&g);              <--- もちろん渡す方も参照で。
}

trait Command {
    fn run(&self);
}

struct Get {}

impl Command for Get {
    fn run(&self) {
        println!("Get!");
    }
}

fn exec(cmd: &Command) {   <--- たしかにサイズの問題は解消だね。
    cmd.run();
}
```

#### [2020-09-20 コメントもらったので修正] Warningへの対処
上記の対処によりコンパイルエラーは解消されるものの以下のように警告は残っている。

```
Trait objects without an explicit 'dyn' are deprecated
```

トレイトオブジェクトを使う時は `dyn` を付けて明示的にするのがお作法らしい。
１つ目の事例だと、

```rust
fn exec(cmd: Box<dyn Command>) {
    cmd.run();
}
```

２つ目の事例だと、

```rust
fn exec(cmd: &dyn Command) {
    cmd.run();
}
```

のようにする。



## [E0106] ライフタイムが指示されてないよ。
これも、Rust以外の言語では見ない概念（少なくともコードではっきり明示しろとは言われない）なので、ハマる。
ライフタイムについては以下参照。
https://doc.rust-jp.rs/rust-by-example-ja/scope/lifetime.html

### ソース
```rust:main.rs
fn main() {
    let s = SomeStruct { name: "test" };
    println!("{:?}", s);
}

#[derive(Debug)]
struct SomeStruct {
    name: &str,           <--- 叱られる。
}
```

### 事象
こんなふうに叱られる。

```
missing lifetime specifier E0106 
expected named lifetime parameter Help: consider introducing a named lifetime parameter
```

https://doc.rust-lang.org/error-index.html#E0106

### 回避策

```rust:main.rs
fn main() {
    let s = SomeStruct { name: "test" };
    println!("{:?}", s);
}

#[derive(Debug)]
struct SomeStruct<'a> {      <--- 構造体本体にも必要。
    name: &'a str,           <--- ライフタイムを明示しろというので、明示してやる。
}
```

## [E0515] すぐに消える情報の参照を関数から返すのはダメだよ。
Golangで書いてたら、こんな感じのコード、ほうぼうで書くと思うのだよね・・・。

### ソース
```rust:main.rs
fn main() {
    let s = new_some_struct("test");
    println!("{:?}", s);
}

#[derive(Debug)]
struct SomeStruct<'a> {
    name: &'a str,
}

fn new_some_struct(name: &str) -> &SomeStruct {
    &SomeStruct { name }            <--- 叱られる。
}
```

### 事象
こんなふうに叱られる。

```
cannot return reference to temporary value E0515 
returns a reference to data owned by the current function
```

### 回避策

```rust:main.rs
fn main() {
    let s = new_some_struct("test");
    println!("{:?}", s);
}

#[derive(Debug)]
struct SomeStruct<'a> {
    name: &'a str,
}

fn new_some_struct(name: &str) -> SomeStruct {
    SomeStruct { name }            <--- おとなしく、参照は外してしまおう。
}
```

## [E0597] 参照で渡すその値は、そんなに長く生きられないよ。

### ソース
```rust:main.rs
fn main() {
    let mut x = &SomeStruct { name: "xxx" };
    {
        let y = SomeStruct { name: "yyy" };
        x = &y;    <--- 叱られる。
    }
    println!("{:?}", x);
}

#[derive(Debug)]
struct SomeStruct<'a> {
    name: &'a str,
}
```

### 事象
こんなふうに叱られる。

```
`y` does not live long enough E0597 
borrowed value does not live long enough
```

https://doc.rust-lang.org/error-index.html#E0597

### 回避策
ブロックスコープは、本当にそのブロックの中で完結するコードを収めましょう。

```rust:main.rs
fn main() {
    let mut x = &SomeStruct { name: "xxx" };

    let y = SomeStruct { name: "yyy" };
    x = &y;     <--- ブロックを取っ払えば、同時にスコープも消える。

    println!("{:?}", x);
}

#[derive(Debug)]
struct SomeStruct<'a> {
    name: &'a str,
}
```

# まとめ
「所有権」と「ライフタイム」について熟知するまでは、ひたすらRustコンパイラに叱られ続けるんだろうなぁ。