Rustにはシャローコピーがわからない

※ 小説です
※ 読むとRustや所有権・参照とちょっとだけ仲良くなれるかもしれません
※ まとめやメッセージの類は最後の[あとがき](#あとがき)に書いてあります(読んで)

# プロローグ

放課後のチャイムを合図に親友のCSSちゃんが現れた。

CSS「TSちゃん放課後ヒマでしょ？駅前にできたECサイトのデザイン見ていかない？」

TypeScript「気になる！...けどごめんね、今日は美化委員会の仕事があるんだ。」

CSS「えー？今日委員会だったっけ？あの偉そうな堅物とすることなんてある？」

TS「偉そうなって...(苦笑)、うーん、まぁ、ちょっとね。埋め合わせに今度新しいライブラリ紹介するから！」

CSS「しょうがないなぁ」

魅力的な誘いを断ってしまった私は、足早に隣のクラスの彼女の元へと向かった。

TS「ふふふ...今日はとっておきのネタがあるからね...」

美化委員会の仕事があるというのは、半分本当で半分嘘である。

委員会ではソースコードを綺麗に書く活動を行っている。その一環で、2人一組でペアプロ・コードレビューを行い、可読性の高いソースコードを書く練習が課せられているのだ。

だけど、、、

Rust「...？」

教室のドアでキョトンとした仏頂面に鉢合う。私のペアであるRustちゃんは、すでにコートを着込み下校の構えをしていた。

TS「帰ろうとするの早くない？！」

Rust「...もう放課後ですから...」

TS「でも先週の委員会活動、Rustちゃんサボったよね...？」

Rust「...活動内容が曖昧だったので...」

Rustちゃんは目を合わせず答えてくる。彼女はすごい人見知りらしく、私とペアを組むことになってからずっと寡黙であった。

TS「だから改めて今日代わりの活動をしようって約束したはずだけど...まぁいいや。とりあえずRustちゃんとお話したいなって思ってさ」

今日はそんな彼女と仲良くなろうと、私なりに「話題」を持ってきたのだった。

# ディープコピーとシャローコピー

TS「この前面白い記事見つけたんだよ！」

https://qiita.com/silane1001/items/ae2e491abd64c01c7f3e

TS「私つい最近まで、ディープコピーをするのに、構造体を文字列化する必要があったんだよね...」

Rust「？...そう、だったんですね...？」

歯切れの悪い回答が返ってくる...言葉だけでは伝わっていないのかもしれない。

TS「ディープコピーというのはあれだよ！プログラミング**初見殺しあるある**！！こんなやつ！」ｶﾀｶﾀ...

```ts:TypeScript
const arr: number[] = [1, 2, 3];
const arr2: number[] = arr;

arr2[0] = 10;

console.log(arr);
// 出力: [ 10, 2, 3 ]
```

TS「`arr`を`arr2`に**コピーした**と思ってたのに`arr2`の中身をいじったら`arr`も変更されちゃうってネタ！実は**参照がコピーされていた**だけってのがオチで...」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/1abec475-3ecd-e6db-df39-b1d4872c4b7b.png)

TS「じゃあ[スプレッド構文](https://typescriptbook.jp/reference/values-types-variables/array/spread-syntax-for-array)でコピーすればいいじゃん、って発想になって、さっきの例だと確かに上手く行くんだけど」

```ts:TypeScript
const arr: number[] = [1, 2, 3];
const arr2: number[] = [...arr];

arr2[0] = 10;

console.log(arr);
// 出力: [ 1, 2, 3 ]
console.log(arr2);
// 出力: [ 10, 2, 3 ]
```

TS「2重配列になると結局また同じ問題が再発しちゃう！」

```ts:TypeScript
const arr: number[][] = [[1, 2, 3], [4, 5, 6]];
const arr2: number[][] = [...arr];

arr2[1] = [7, 8, 9];
console.log(arr);
// 出力: [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] // 予想通り
console.log(arr2);
// 出力: [ [ 1, 2, 3 ], [ 7, 8, 9 ] ]

arr2[0][0] = 10;

console.log(arr);
// 出力: [ [ 10, 2, 3 ], [ 4, 5, 6 ] ] // ?!?!
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/a90627ff-39b0-8d76-f958-e3e8ad97fb8b.png)

TS「これは浅いコピー...つまり**シャローコピー**だから起きちゃう事故なんだ。シャローコピーを回避するため、以前は配列や構造体を最深部まで深いコピー、いわゆる**ディープコピー**をするのに`JSON.stringify`を使ってたんだけど、ついに`structuredClone`でそれが可能に...」

Rustちゃんの表情を見てハタと止まった。本気で不思議そうな顔が貼りついていた。

Rust「...」

TS「あの、Rustちゃん...？」

Rust「...最初の`const`のところから何を言っているのかわからないわ...」

......

やってしまった...

.......

また、やってしまった...相手のことを全く気にせずずっとしゃべり続けてしまった...

...私は昔...JSだった時から突っ走ってしまう癖があった。そして[計算を間違え](https://zenn.dev/ymmt1089/articles/20220603_big_number) [^calcmiss]たり[nullとundefinedを混同し](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Equality)たり[undefinedを変数のように扱っ](https://zenn.dev/lollipop_onl/articles/eoz-using-undef-on-js)たりなどの数々のおっちょこちょいな性格もあって、周りからはドジっ子扱いされていた。それが嫌で陽キャを演じていた私だったが...

[^calcmiss]: だいぶ後に気づきましたがリンク先のミスはJSに限らずRustを始め浮動小数点型を採用しているかなりの言語でおきます。言語に関係なく多倍長整数ライブラリ等を導入することで解決できたはずです。でもなんかJSって計算ミスしやすいイメージなんですよね...ここに上げたもの以外にもNo Context JS仕様は色々あるはずでまぁその雰囲気を出したかったのだと受け取ってもらえると幸いです(ごめんねJSちゃん)

TS「やっぱり私は陰キャ言語相手のことを考えられないコミュ障...UDPでしか会話できない...」🌀ｸﾞﾙｸﾞﾙｸﾞﾙｸﾞﾙ🌀

CSS「...心配になって付いてきてしまったけど、またTSちゃん鬱モードに入っちゃってる...Rustちゃん何したのさ？」

Rust「いえ、私は何も...」

CSS「何もしてないって？TSちゃんを無視したりだって嫌がらせよ？」

Rust「説明していただいたソースコードが読めない、とは言いました。」

CSS「ソースコードって...これかな」ｶﾁｶﾁｯ

```ts:TypeScript
const arr: number[] = [1, 2, 3];
const arr2: number[] = arr;

arr2[0] = 10;

console.log(arr);
// 出力: [ 10, 2, 3 ]
```

CSS「中身はよくわからないけど、大した行数はないじゃない？Rustちゃんなら平気で読める量では？」

Rust「いえ、茶化したりしているわけではなく、本当に`const`のところからわからないんです。」

![ChatGPT Image 2025年3月26日 21_15_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/26c3d02d-6fe7-4339-b7d7-8f52faec8652.png)

# TypeScriptの`const`とRustの`let`

TS「`const`と書くのにも関わらず、中身を変更可能だからかな...？たまに指摘されます...」

CSS「あ、TSちゃん復活した」

TS「今回の話に関わるので解説するね。`const`が保証するのは変数に格納された**値**が以降で変更されないこと」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/e888c1a2-c2b4-6172-944b-d0684f1c67c7.png)

TS「配列の場合、`const`は変数に入っている参照の再代入は防いでくれるけど、**参照先の値は変更できちゃう**んだよね。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/cdcf1fed-3b18-2ea0-db8a-b02faacc67cc.png)

CSS「Rustちゃんの場合はこれをどう解釈するの？」

Rust「`const`はコンパイル前に値が定まる定数を表します[^const]。TSさんにとっての`const`に一番近い宣言は`let val: &mut T`でしょうか？ここで`val`は変数名、`T`は格納する変数の(参照先の)型です。」

[^const]: この制約のために大体はプリミティブ型が入りますが、コンパイル時に値が決まるならばどのような型でも問題ありません。例えば`&'static str`や`[usize; 3]`みたいなものは指定できます。一方で、動的なヒープ確保が必要になる`String`など、(`const fn`ではない)関数を呼び出さないと値が決まらないような型は指定できないことが大半です。

```rust:Rust
let mut _arr: Vec<usize> = vec![1, 2, 3];
let arr: &mut [usize] = &mut _arr; // このarrはconst arrに相当
```

CSS「(Rustちゃんも他人のこと言えないぐらい意味のわからないコード書いてない...？？)」

Rust「おそらくですが私にとっての`let`による宣言がTSさんの`const`とほぼ同じ意味です。しかし私の場合は、`&mut`をつけて可変参照を取らないと、ホワイトボードに描かれた赤矢印のような可変は得られません。」

CSS「(そして急に饒舌になったなぁ...)」

TS「うーん...もしかしてRustちゃんにとっての`let`は私にとっては`const arr: readonly number[]`かもしれない...」

CSS「(TSちゃんまで呪文を...ｱﾜﾜ)」

CSS「えっと、、**ごめんよくわからなくなってきたのだけど**(大声)、要はTSちゃんとRustちゃんでは書き方が違うから伝わらないっていう、それだけじゃない？」

Rust「いえ、`const`の意味を教えていただいたので読める気がしてきました...しかし、ホワイトボードで議論した内容と私の直感的な理解が一致しないです。」

CSS「(全くわからないと言いつつ結構ちゃんと聞いていたのでは...？)」

TS「うーん...じゃあ試しに、元のコードを私がRustで書いてみるね」

# Rustの所有権と`Clone`トレイト

～ 調べながら書くこと数十分後 ～

TS「配列に`[T; n]`みたいなのと`Vec<T>`があって迷ったけど、私に合わせて、可変長な`Vec<T>`にしたよ[^array]！」

:::note warn
`[T; n]`は静的配列で、`Vec<T>`はヒープにメモリを確保する可変長配列です。以降、本小説において「配列」は可変長配列`Vec<T>`を指すこととします。

- [配列とスライス - Rust By Example 日本語版](https://doc.rust-jp.rs/rust-by-example-ja/primitives/array.html)
- [ベクタ型 - Rust By Example 日本語版](https://doc.rust-jp.rs/rust-by-example-ja/std/vec.html)
:::

[^array]: 以降で詳しく解説しますが、配列型には`Clone`トレイト及び`Copy`トレイトの両方が実装されていて解説の上で不都合だったので`Vec<T>`を選んだ経緯もあります。

```rust:Rust(コンパイルエラー)
fn main() {
    let arr: Vec<usize> = vec![1, 2, 3];
    let arr2: Vec<usize> = arr;

    arr2[0] = 10;
    
    println!("{:?}", arr);
}
```

TS「できた！けど、ありゃりゃ...コンパイルエラーだ...？...長い！！」

```bash:エラー
$ rustc main.rs
error[E0596]: cannot borrow `arr2` as mutable, as it is not declared as mutable
 --> main.rs:5:5
  |
5 |     arr2[0] = 10;
  |     ^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
3 |     let mut arr2: Vec<usize> = arr;
  |         +++

error[E0382]: borrow of moved value: `arr`
 --> main.rs:7:22
  |
2 |     let arr: Vec<usize> = vec![1, 2, 3];
  |         --- move occurs because `arr` has type `Vec<usize>`, which does not implement the `Copy` trait
3 |     let arr2: Vec<usize> = arr;
  |                            --- value moved here
...
7 |     println!("{:?}", arr);
  |                      ^^^ value borrowed here after move
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let arr2: Vec<usize> = arr.clone();
  |                               ++++++++

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0382, E0596.
For more information about an error, try `rustc --explain E0382`.
```

TS「エラー自体は2つみたいだね...えっと一つ目は」

```
error[E0596]: cannot borrow `arr2` as mutable, as it is not declared as mutable
 --> main.rs:5:5
  |
5 |     arr2[0] = 10;
  |     ^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
3 |     let mut arr2: Vec<usize> = arr;
  |         +++
```

TS「cannot borrow `arr2` as mutable, as it is not declared as mutable...和訳すると、『`arr2`は可変で宣言されていないため、`arr2`を可変で借用できません。』」

TS「そしてhelpに、consider changing this to be mutable...これも和訳すると、『これを可変になるように変えることを検討してください』...？」

Rust「先ほどTSさんがちらりと`readonly`というキーワードを口にしていたと思うのですが、`let`はデフォルトで`readonly`が付与されていると考えるとわかりやすいです。`mut`は、この`readonly`を外す操作に近いかと。」

TS「じゃあ`arr2`に`mut`を付ければ解決しそうだね」

```diff_rust:Rust
fn main() {
    let arr: Vec<usize> = vec![1, 2, 3];
-    let arr2: Vec<usize> = arr;
+    let mut arr2: Vec<usize> = arr;

    arr2[0] = 10; // arr2は可変なのでおｋ
    
    println!("{:?}", arr);
}
```

TS「でも2つ目のエラーは解決しなかったみたい」

```bash:エラー
$ rustc main.rs
error[E0382]: borrow of moved value: `arr`
 --> main.rs:7:22
  |
2 |     let arr: Vec<usize> = vec![1, 2, 3];
  |         --- move occurs because `arr` has type `Vec<usize>`, which does not implement the `Copy` trait
3 |     let mut arr2: Vec<usize> = arr;
  |                                --- value moved here
...
7 |     println!("{:?}", arr);
  |                      ^^^ value borrowed here after move
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let mut arr2: Vec<usize> = arr.clone();
  |                                   ++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
```

TS「borrow of moved value: `arr`...『移動された`arr`の値を借用した』？」

Rust「...("これ"を説明する時がまた来てしまった...)」

Rust「...`arr2`に、`arr`が持っていた`vec![1, 2, 3]`という値の**所有権**が移動(ムーブ)したため、`arr`は使用できない、という意味です。」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/1824c4e9-8242-94ec-7f14-a29540092eb6.png)

Rust「使用できないのにも関わらず、`println!`で参照しているのでエラーになっています。借用という言葉は私には参照と同義です。」

TS「**参照がコピーされるわけじゃない**んだね...あ、さっきと同じくエラー文に解決策も書いてる」

```
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let mut arr2: Vec<usize> = arr.clone();
  |                                   ++++++++
```

Rust「(あれ？拒絶されなかった...)」

Rustちゃんは何か不思議な表情をしていたが、私はそのまま続けた。

TS「えっと、consider cloning the value if the performance cost is acceptable...『パフォーマンスコスト的に許せるなら値のクローンを作ることを検討してください』...？」

TS「`clone`というメソッドを呼べばいいんだね！このメソッドは`Vec<usize>`固有の物？」

Rust「いえ、`Clone`トレイトを実装した型であればどれもが持ち合わせています。」

TS「トレイト？」

Rust「TSさんで言う`interface`に該当するもの[^interface]です。ただしトレイトにはフィールドを指定する機能はありません。」

[^interface]: TypeScriptでは[かなり色々な使われ方をしているキーワード](https://www.wakuwakubank.com/posts/636-typescript-interfaces/)のようですね。今回のはclassにimplementsする使い方をするinterfaceです。

- [クローン - Rust By Example 日本語版](https://doc.rust-jp.rs/rust-by-example-ja/trait/clone.html)
- [Clone in std::clone - Rust](https://doc.rust-lang.org/std/clone/trait.Clone.html)

```rust:Rust
pub trait Clone: Sized {
    fn clone(&self) -> Self;

    // 自動実装される`clone_from`は省略
}
```

```ts:TypeScript風に書くと
interface Clone<T> {
    clone(): T;
}
```

Rust「名前から察しが付くと思いますが、`clone`メソッドを使うと元の値のクローンが作られます。元の変数の所有権は奪いません。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/4c00fae8-7cf2-17fd-8436-541a474fed8a.png)

TS「...ということはもしかして私が2つ目に書いたスプレッド構文を使うコードと同じ結果になるのでは...？」

CSS「とりあえず動かしてみればわかるんじゃない？」

TS「そうだね、ついでに`arr2`の出力も加えてみるよ」

```diff_rust:Rust
fn main() {
    let arr: Vec<usize> = vec![1, 2, 3];
-    let mut arr2: Vec<usize> = arr;
+    let mut arr2: Vec<usize> = arr.clone();

    arr2[0] = 10;

-    println!("{:?}", arr);
+    println!("arr = {:?}", arr);
+    println!("arr2 = {:?}", arr2);
}
```

TS「コンパイルは通った！、、実行結果は...」

```bash:実行結果
$ rustc main.rs
$ ./main
arr = [1, 2, 3]
arr2 = [10, 2, 3]
```

TS「やっぱりスプレッド構文と同じだ！！」

Rust「結局初見殺しあるあるの正体はわかりませんでしたね...」

TS「でもまだシャローコピーである可能性が残っているかも」

CSS「じゃあ同じ感じで3つ目のコードをRustで書いてみたら？」

TS「がんばる！」ｶﾀｶﾀ...

```rust:Rust
fn main() {
    let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let mut arr2: Vec<Vec<usize>> = arr.clone();

    arr2[1] = vec![7, 8, 9];
    
    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);

    arr2[0][0] = 10;

    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);
}
```

TS「今回はエラーなく一発でコンパイル通ったみたい」

```bash:実行結果
$ rustc main.rs
$ ./main
arr = [[1, 2, 3], [4, 5, 6]]
arr2 = [[1, 2, 3], [7, 8, 9]]
arr = [[1, 2, 3], [4, 5, 6]]
arr2 = [[10, 2, 3], [7, 8, 9]]
```

TS「**デ　ィ　ー　プ　コ　ピ　ー　さ　れ　て　る　！**」

Rust「`clone`メソッドは構造体や配列の要素に対し再帰的に呼び出されるので、`Vec`の要素になっている`Vec`についても中身がクローンされます。そのため、所有権譲渡も発生せずコンパイルが通っていたわけですね[^clone]。」

[^clone]: 裏を返すと`Clone`トレイトが実装されていない型が`Vec`の要素になっていた場合、つまり、`Clone`を実装しない`T`に対する`Vec<T>`については、`Clone`が実装されず`clone`メソッドを呼び出すことはできません。ジェネリクスを上手く指定することでこのような実装が可能です。

TS「最初から全部ディープコピーされるなんて...もしかしてRustちゃんには**シャローコピー初見殺しあるあるが伝わらない**...？」

そんな...せっかく話題を共有できると思ったのに...

CSS「でもTypeScriptだけじゃなくPythonとか多くの言語ができるらしいことが、Rustちゃんにはできないってことなんだね？意外な一面を見たかも」ﾆﾔﾆﾔ

Rust「できなくはないはずですよ」

TS「...ほえ？」

Rustちゃんは、ムッとした表情を貼り付けながら

Rust「だから、TSさんがホワイトボードに描いたような、参照だけを複製するようなコードも、書けなくはないです。」

そう言ってキーボードの前に座った。

# Rustの不変参照と可変参照

- 参考元: [参照と借用 - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch04-02-references-and-borrowing.html)

(読者の方へ: ここからちょっと長いので頑張ってください)

## 不変参照

Rust「その前に、私にとっての参照とはどういうものかを解説したほうが良さそうですね。基本的には、不変参照と可変参照の二種類があります。」

TS「可変参照についてはさっき少し触れていたような？」

Rust「そうですね。しかし説明の順番のため、まずは不変参照についてです。」ｶﾀｶﾀ...

```rust:Rust
// vecの型&Vec<Vec<usize>>は、vecがVec<Vec<usize>>型の値の不変参照であることを表す
fn print_vec(vec: &Vec<Vec<usize>>) {
    for i in vec {
        for j in i {
            print!("{} ", j);
        }
        println!("");
    }
}

fn main() {
    let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let arr_ref: &Vec<Vec<usize>> = &arr; // &をつけることで参照を取れる

    print_vec(arr_ref);

    // 関数に渡す場合は直接こう書く方が普通
    print_vec(&arr);
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/aa121279-f24b-5b66-892e-f702459d4dd9.png)

Rust「`&arr`のように変数の前に`&`を付けることで、`arr`という変数が持つ値への不変参照を取れます。名前の通り、不変参照に対して変数の中身を変更する操作は不可能です[^immut]。」

[^immut]: 不変性は基本的には再帰的に成り立ちますが、フィールドのどこかに可変参照を内包するような構造体については、その不変参照からも可変参照を通して"中身を変えられる"ことに気を付けてください。

```rust:Rust(コンパイルエラー)
fn main() {
    let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let arr_ref: &Vec<Vec<usize>> = &arr;

    arr_ref[0][0] = 10; // コンパイルエラー。不変参照では変更操作ができない
}
```

CSS「`&`で参照ってC言語っぽい...？うーん...C言語先生の授業のトラウマが...」

TS「`&`を使っているせいで難しく見えてるだけかも、さっき話した通り私にも参照の考えはあるし。ところで、C言語のポインタには不変・可変の区分はなかったよね？不変というだけでかなり強い制限な気がするけど、どんな場面で使われるの？」

Rust「不変参照はあるデータに依存して分岐したり、例にある`print_vec`関数のようにデータそのものを出力する場合に使われることが多いです。」

TS「覗くだけなら可変である必要はないもんね。」

CSS「でもできるなら参照を使いたくないような...参照じゃなきゃだめ？」

TS「使わないで書いてみると...こんな感じかな...」

```rust:Rust
fn print_vec(vec: Vec<Vec<usize>>) {
    for i in vec {
        for j in i {
            print!("{} ", j);
        }
        println!("");
    }
}

fn main() {
    let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];

    print_vec(arr);
}
```

TS「特にコンパイルエラーも起きなかったけど...」

CSS「大丈夫そうじゃん」

Rust「もう一回`print_vec`してみてくれますか？」

TS「...？何か変わるの...？」

```diff_rust:Rust(コンパイルエラー)
fn main() {
    let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];

    print_vec(arr);

+    print_vec(arr);
}
```

TS「コンパイルエラーになった！なんで？！」

```bash:エラー
$ rustc main.rs
error[E0382]: use of moved value: `arr`
  --> main.rs:15:15
   |
11 |     let arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
   |         --- move occurs because `arr` has type `Vec<Vec<usize>>`, which does not implement the `Copy` trait
12 |
13 |     print_vec(arr);
   |               --- value moved here
14 |
15 |     print_vec(arr);
   |               ^^^ value used here after move
   |
note: consider changing this parameter type in function `print_vec` to borrow instead if owning the value isn't necessary
  --> main.rs:1:19
   |
1  | fn print_vec(vec: Vec<Vec<usize>>) {
   |    ---------      ^^^^^^^^^^^^^^^ this parameter takes ownership of the value
   |    |
   |    in this function
help: consider cloning the value if the performance cost is acceptable
   |
13 |     print_vec(arr.clone());
   |                  ++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
```

TS「use of moved value: `arr`...『すでに移された値`arr`を使ってる』...？」

Rust「変数間だけではなく関数の引数に変数が与えられる場合も引数への**所　有　権　譲　渡**が行われるため、エラーになっています。譲渡されたことが『移った』と表現されています。」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷｶｷｶｷｶｷ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/8fb7ef29-276f-f150-4459-77dc656b4281.png)

そこまで大した内容ではないはずなのに、強い口調で話しながらRustちゃんは熱心に図を描き殴っていた。出会った時のRustちゃんからは全く想像できないその姿に、戸惑いながらも。

TS「しょゆうけんのじょうと、っていうのは、さっきから点線で描いてるやつだね...つまり一回目の`print_vec`で`arr`から所有権が奪われるから、二回目の呼び出し箇所でエラーになるのかな？」

こう私が答えると、どこか安心したように彼女は続けた。

Rust「そうです。配列の出力には`arr`の所有権は不要ですから、本体ではなく、所有権譲渡なしで使える参照だけあれば十分です。それが`print_vec`の引数`vec`の型が参照型`&Vec<Vec<usize>>`である理由でした。」

TS「不変参照が必要というよりは、不変参照で十分ってことだね。helpに書いているみたいに`clone`を使ってもエラーは消えるのだろうけど、クローンするまでもないという感じ...？」

Rust「はい、`clone`を呼び出す場合、メモリ使用量は倍に増えます。一方、**不変参照なら余計なメモリアロケーションを回避できます**。`arr`本体の代わりに不変参照としてリソースを"借りて"いるので、参照のことを**借用**とも言います。」

CSS「`clone`で思い出したけど、さっきまでこんな難しい話なかったような...よくよく思い返してみれば、所有権でコンパイルエラーになって、参照の話が回避されていきなりディープコピーのコードにたどり着いていたよね...アレ？もしかして**所有権のおかげで難しい参照の話を回避できていた**...？」

TS「私のコードは言うなれば『無断借用』状態になっていたけど、Rustちゃんの場合は**所有権のおかげでリソースの位置や借用関係がはっきりしている**よね。『あげられない・貸せない時はクローン』ってことで、参照記号(`&`)なしではディープコピーのようなコードしか書けなかったのかも。」

Rust「言われてみれば、最初にTSさんのコードを直感的に理解できなかったのは、どこに借用...参照が生じているのかわからなかったからですね。」

CSS「なんかもろもろの解決の糸口が見えてきたね」

:::note info
どうして関数の引数も所有権を奪うのでしょうか？詳しくは書きませんがヒントを。この仕組みや`clone`、そして後述する可変参照を応用すれば「値渡し」と「参照渡し」を区別してどちらも記述することが可能ですよね。つまり都合が良いからです。

<details><summary>具体例</summary>

```rust:Rust
#[derive(Clone, Copy, Debug)]
struct Hoge {
    val: usize,
}

fn value_watashi(mut hoge: Hoge) {
    hoge.val = 100;
    println!("value_watashi: {:?}", hoge);
}

fn mutref_watashi(hoge: &mut Hoge) {
    hoge.val = 100;
    println!("mutref_watashi: {:?}", hoge);
}

fn main() {
    let mut hoge = Hoge { val: 0 };
    value_watashi(hoge);
    println!("main: {:?}", hoge);
    mutref_watashi(&mut hoge);
    println!("main: {:?}", hoge);
}
```
</details>

関数の引数も所有権を奪うというよりは、「変数が評価される際は所有権譲渡が起こるかも」と考えた方が自然な捉え方かもしれません。[おまけのCopyトレイトの節](#おまけ-copyトレイト)でも解説していますが、デフォルトで所有権譲渡が行われる仕様のため「余計なメモリアロケーションを避ける」ことができています。
:::

## 可変参照

Rust「次は可変参照についてです。先ほどの例がコンパイルエラーにならないように書き直してみました。」

```rust:Rust
fn main() {
    let mut arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let arr_mref: &mut Vec<Vec<usize>> = &mut arr;

    arr_mref[0][0] = 10;
}
```

Rust「変数の可変参照を取るには、元の変数が可変である必要があります。そのため、`let mut arr`としています。記法として違うのは`&`ではなく`&mut`としている点ですね。」

TS「可変参照はどんな時に使われるの？」

Rust「主に関数呼び出しで引数に副作用が生じる(または生じさせたい)場合に使います。関数については、例えば以下に書くソートとかですね[^sort]。他は、競技プログラミング等で再帰関数で使われることが多いです。」ｶﾀｶﾀ...

[^sort]: スライスに存在する`sort`メソッドの車輪再開発です。

```rust:Rust
// vecの型&mut Vec<usize>は、vecがVec<usize>型の値の可変参照であることを表す
fn sort_vec(vec: &mut Vec<usize>) {
    // select sort
    for i in 0..vec.len() {
        let mut min = i;
        for j in i..vec.len() {
            if vec[j] < vec[min] {
                min = j;
            }
        }
        vec.swap(i, min);
    }
}

fn main() {
    let mut arr: Vec<usize> = vec![3, 1, 4, 1, 5, 9, 2];

    sort_vec(&mut arr); // &mut で変数の可変参照が取れる

    println!("{:?}", arr); // [1, 1, 2, 3, 4, 5, 9]
}
```

Rust「例えばPythonにある`sorted`みたいに、引数で配列を受け取り返り値で返す方法も考えられますが、それだけでは不便です[^pythonmut]。」ｶﾀｶﾀ...

[^pythonmut]: Pythonの場合は元の配列に一切手が加わりません。Rustの場合はどっちとも言えず、`clone`を使って複製したものを渡す場合は値渡しのため元の配列に影響がありませんが、そのまま渡す場合はそもそも所有権が奪われます。

```rust:Rust (&mutを使わない場合)
fn sorted(mut vec: Vec<usize>) -> Vec<usize> {
    // select sort
    for i in 0..vec.len() {
        // omit details
    }

    vec
}

fn main() {
    let arr: Vec<usize> = vec![3, 1, 4, 1, 5, 9, 2];

    let arr = sorted(arr);

    println!("{:?}", arr);
}
```

Rust「関数の返り値にするほどではない、しかし副作用を起こすために参照渡しを行いたい。そんな時に使うと効果的です。」

CSS「(Rustちゃん、自分の話ができて楽しくなってきてるのかな、饒舌さがマックスに...)」

TS「可変参照`&mut`があれば初見殺しあるあるを再現できそうだね！」

Rust「いえ、残念ながらそうでもないんです。」

## 参照に関する制約

Rust「ここまでの説明に加え、`&`と`&mut`には以下に示す制約があります。この制約のため、あるあるを実現できません。」

1. ある変数への参照は、不変参照か可変参照の、どちらか片方の種類の参照のみしか同時に存在できない
2. 不変参照は同時に複数存在することができる
3. 可変参照は一つしか存在できない
4. 参照は変数のライフタイムが有効な範囲でのみ存在できる([後述](#ライフタイム制約))

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/2f5d9c54-d505-e61b-91bf-e4d365db0102.png)


CSS「不変か可変かだけで頭が痛いのになんか多いな...？なぜこんなに制約が...？」

Rust「最後に示したライフタイムの話は一旦後にするとして、最初の3つについて解説します。何かわかりやすい例え...そうですね...」ｶﾁｶﾁｯ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/519ac71e-fbbf-aec8-dc5e-b97115d48cd1.png)

TS「これは...会計兼予算編成委員会のスプレッドシート...？しかも共同編集中みたいだけど」

CSS「なんでRustちゃんにアクセス権が...？」

Rust「私は会計兼予算編成委員会も兼任していますから。」

TS「へー、ということはRustちゃんは美化兼会計兼予算編成委員なんだね」

CSS「Rustちゃん予算編成委員もサボってるん？サボるくせに兼任してるん？？そしてそのスプレッドシートは私たちに見せて大丈夫なのか...？！」

ツッコミが追い付いていないCSSちゃんなのであった。それにしてもRustちゃん、結構度胸あるなぁ

> 一方その頃、会計兼予算編成委員会では...
>
> Haskell「どの部活動もChatGPTがどうのとかNovel AIがどうのとかでサブスク入りすぎですわ！とてもじゃないけど承認できないわ。」
> Elixir「そうですね。特に委員会を中心に予算を減らしましょう。」
> Haskell「では私が編集するので範囲にロックを掛けますわ」

Rust「あ、変化がありましたよ」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/70dff214-cf11-1770-56c1-74bbf80fa4db.png)

TS「風紀委員会が網掛けになったね。この範囲にロックが掛けられて編集ができなくなってる...？あ、値が変わった」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/6b5aca7b-3af5-7b71-a2d4-16d04b3730b7.png)

> Haskell「風紀委員の方たちにChatGPTなんて不要ですわ！9000円でよろしくてよ」
> Elixir「さすがに反発が起きるのでは...」
> Haskell「それもそうですわね。では去年と同じで90000円ということで」
> Elm「(お姉さまが委員長になってからこの委員会不安しかない件について)」

CSS「さすがに9000円は何かの間違いでしょ。編集中なんじゃない？」

Rust「ということは、これを**不変として捉えるのは避けたほうがいい**ですね。具体的には、網掛けがある間はこの範囲をコピペするのは避けるべきです。」

TS「あっ！1番の『不変参照か可変参照の、どちらか片方の種類の参照のみしか同時に存在できない』だね！」

CSS「可変参照でHaskell委員長？が編集中だから、不変参照は取れないってことか」

> Haskell「ついでに美化委員会の奴らの予算も減らしてやりましょ。おーっほっほっほ」
> Elm「(お姉さまいつからこんなキャラになったんだっけ...)」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/e74be032-9a6e-427f-02fe-b6bc056d2a7f.png)

TS「あー－！！なんかついでに私たちの予算まで減らされているんだけど！！！Rustちゃん直せない...？」

Rust「ロックが掛けられているので無理ですね。それにもしロックが掛からないものとして、同時に編集したら**仁義なき編集合戦の無限ループになります**...」

CSS「あっ、これが3番の『可変参照は一つしか存在できない』ってことか。確かに**同時に複数の場所から変更されると混乱しちゃう**かも」

TS「ちょっと...誰か...予算減額を...止めて...」

> Haskell「今日はこんなところですわね。お疲れ様でしたわ。」
> Elixir「お疲れさまでしたー」
> Elm「(非承認のままだし色々雑すぎだろ。てかロック掛ける意味ってあったんか？)」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/78e15361-c76b-60ea-47f1-6ae7fe95aeff.png)

CSS「網掛けが消えて人影も消えた...」

TS「えっと、もう可変ではなくなったのだろうし不変と捉えてコピペできるね、2番の『不変参照は同時に複数存在することができる』かな...？」

Rust「例えとして無理がありそうですがそんなところですね。」

CSS「制約の理由はなんとなくわかったけど、それがどうして初見殺しあるあるが実現できないことにつながるの...？」

Rust「主に1番の『不変参照か可変参照の、どちらか片方の種類の参照のみしか同時に存在できない』が効いてきます。実際に書いてみればわかるかなと。」

TS「やってみる！」

## 「あるある」を可変参照で書いてみる

```rust:Rust(とりあえず途中まで。コンパイルエラー)
fn main() {
    let mut arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let arr2: &mut Vec<Vec<usize>> = &mut arr;

    arr2[1] = vec![7, 8, 9];
    
    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);
}
```

TS「案の定エラーが出たね...」

```
error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
  --> main.rs:26:28
   |
22 |     let arr2: &mut Vec<Vec<usize>> = &mut arr;
   |                                      -------- mutable borrow occurs here
...
26 |     println!("arr = {:?}", arr);
   |                            ^^^ immutable borrow occurs here
27 |     println!("arr2 = {:?}", arr2);
   |                             ---- mutable borrow later used here
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0502`.
```

Rust「ソースコードからはわかりにくいですが、`println!`関数(ホントは[マクロ](https://doc.rust-jp.rs/book-ja/ch19-06-macros.html)だけどとりあえず関数と言っておこう...)は変数の不変参照を取るようにできています。」

TS「そっか、`arr2`で可変参照借用中だから、`arr`の不変参照が取れなくてエラーになってるんだね...」

Rust「`arr`の出力を最後に持っていけば、`arr2`がもう使われないため、可変参照は自動で無効化されるのでコンパイルが通ります。」ｶﾀｶﾀ...

```rust:Rust
fn main() {
    let mut arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let arr2: &mut Vec<Vec<usize>> = &mut arr;

    arr2[1] = vec![7, 8, 9];
    
    // println!("arr = {:?}", arr); // ここでの出力は諦める
    println!("arr2 = {:?}", arr2);

    arr2[0][0] = 10;

    // println!("arr = {:?}", arr); // ここでの出力は諦める
    println!("arr2 = {:?}", arr2);
    
    // ここでarr2が自動的に無効化される

    println!("arr = {:?}", arr);
}
```

```bash:実行結果
$ rustc main.rs
$ ./main
arr2 = [[1, 2, 3], [7, 8, 9]]
arr2 = [[10, 2, 3], [7, 8, 9]]
arr = [[10, 2, 3], [7, 8, 9]]
```

CSS「あれ？実行結果がTSちゃんのシャローコピーと全然違くない...？」

Rust「説明を簡単にするために`arr2`は`arr`**自体の可変参照**としたのが原因ですね。図にするとこんな感じです。」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/75965c89-adf6-d883-b044-2d1f0d906090.png)

CSS「元の図はこっちだね。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/ebdaa24b-a284-e571-1873-67282fe127e8.png)


TS「うーんと...えーっと...あーんと...あっ、『参照の配列』が必要でそれぞれの配列自体の所有権は`arr`と`arr2`のそれぞれにある感じ...？でも難しそうだよぉ」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/b7c1361e-ca78-e5ec-1a5d-3e7ed1c48ed4.png)

Rust「さすがにこれは私が書きますね。こんな感じでしょうか」ｶﾀｶﾀ...

```rust:Rust
fn main() {
    let mut arr: Vec<Vec<usize>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let mut arr2: Vec<&mut Vec<usize>> = arr.iter_mut().collect();

    let mut new_vec = vec![7, 8, 9];
    arr2[1] = &mut new_vec;

    // println!("arr = {:?}", arr); // ここでの出力は諦める
    println!("arr2 = {:?}", arr2);

    arr2[0][0] = 10;

    // println!("arr = {:?}", arr); // ここでの出力は諦める
    println!("arr2 = {:?}", arr2);
    
    // ここでarr2が自動的に無効化される

    println!("arr = {:?}", arr);
}
```

Rust「最終的な`arr`と`arr2`の状態は希望と一致しているはずです。」

```bash:実行結果
$ rustc main.rs
$ ./main
arr2 = [[1, 2, 3], [7, 8, 9]]
arr2 = [[10, 2, 3], [7, 8, 9]]
arr = [[10, 2, 3], [4, 5, 6]]
```

TS「大きく変わったのは

```rust:Rust
let mut arr2: Vec<&mut Vec<usize>> = arr.iter_mut().collect();

let mut new_vec = vec![7, 8, 9];
arr2[1] = &mut new_vec;
```

の部分だね」

Rust「はい。`Vec<&mut Vec<usize>>`に注目すると、`arr2`が『参照の配列』になっていることがわかります。`iter_mut`は『要素(ここでは`Vec<usize>`型の値が要素)それぞれへの可変参照のイテレータを得る』メソッドで、`collect`は『イテレータから新しい配列(など)を得る』メソッドです。組み合わせることで、『参照の配列』が得られます。」

CSS「わざわざ`new_vec`という変数を設けているのはなぜ？」

Rust「4番の『参照は変数のライフタイムが有効な範囲でのみ存在できる』の影響です。`&mut vec![7, 8 ,9]`としてしまうと、`vec![7, 8, 9]`**を所有する変数が存在しない**ことになってしまいます。」

TS「`&mut`はあくまでも借用だもんね。貸してくれる相手...参照先がいなければそもそも借りられないわけだ」

Rust「はい、ですから、何かしらの変数に`vec![7, 8, 9]`を束縛する必要があったので、`new_vec`に束縛していました。」

TS「...ちょっと待って...？`arr`と`arr2`の型って一致していないとおかしくない...？今って図にするとこういう状態では...？」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/c92e8371-0d67-7848-5dec-76a9df012c82.png)

CSS「それに結局途中の`arr`の状態を出力できてないよね。」

Rust「気づいちゃいましたか...これが『まだあるあるを実現できない』と言った理由です。正確に表現するには、もう少し細工が必要です。」

# 参照の制約を超えたい: `Rc` と `RefCell`

## `RefCell`

Rust「最後のコードで問題となるのは、3番の『可変参照は一つしか存在できない』です。`arr`と`arr2`の型を一致させ対等にするには、両方とも`Vec<&mut Vec<usize>>`型にしなければいけませんが、`Vec<usize>`への可変参照はそれぞれについて一つしか取れないので、`arr`と`arr2`は同時に存在することができません。」

TS「確かに...元はと言えば、`arr`と`arr2`が**どちらからもお互い共通の参照先を変更できてしまう**のが初見殺しあるあるの問題点だもんね。そういうコードはそもそも書けないのか。」

Rust「その無理を押し通すため、もう少し柔軟な"可変参照っぽいもの"を使います。『可変参照中』かどうかは、通常コンパイル前に調べられるのですが、この**借用チェックをランタイム時に行う**、`RefCell<T>`型がそれです。」ｶﾀｶﾀ...

- [RefCellと内部可変性パターン - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch15-05-interior-mutability.html)

```rust:Rust
use std::cell::{RefCell, RefMut, BorrowMutError};

fn main() {
    let x: RefCell<i32> = RefCell::new(5);
    let y: &RefCell<i32> = &x;
    let z: &RefCell<i32> = &x;

    {
        let x_mr: &mut i32 = &mut *y.borrow_mut();
        *x_mr += 1;
    }
    println!("x = {:?}, y = {:?}, z = {:?}", x, y, z);

    *z.borrow_mut() += 1;
    println!("x = {:?}, y = {:?}, z = {:?}", x, y, z);

    // 可変参照が複数ある場合に借用できないことを確認
    {
        let x_mr: &mut i32 = &mut *y.borrow_mut();
        let Ok(x_mr_2): Result<RefMut<i32>, BorrowMutError> = z.try_borrow_mut() else {
            println!("x is already borrowed");
            return;
        };

        println!("x_mr = {:?}, x_mr_2 = {:?}", x_mr, x_mr_2);
    }
}
```

```bash:実行結果
$ rustc main.rs
$ ./main
x = RefCell { value: 6 }, y = RefCell { value: 6 }, z = RefCell { value: 6 }
x = RefCell { value: 7 }, y = RefCell { value: 7 }, z = RefCell { value: 7 }
x is already borrowed
```

Rust「`RefCell<T>`は可変参照そのものではないのですが、『ランタイム時、一時的に可変を得る』ことができる構造体です。」

TS「`y`や`z`は`x`への可変参照じゃなくて、『可変参照を一時的に得られる`RefCell<i32>`への**不変参照**』だから共存できるわけだね。」

Rust「はい。そして**ランタイム時にて可変参照を得る際に**可変参照が複数ないかを確認します。すでに存在する場合はパニックになります。」

CSS「Rustちゃんがヒステリーを起こすってこと...？」

Rust「パニックは、皆さんで言う実行時エラーのことです...」

TS「どういうものかはわかったけど、各場所で何をしているのかがよくわからないかも」

Rust「9行目の`&mut *y.borrow_mut()`が実際に可変参照を得る場所です。`*`記号は『参照外し』と言って、`&T`や`&mut T`、`RefMut<T>`等[^deref]から`T`型の値を得る操作です。その後、改めて`&mut`を付けることで可変参照を得られます。9行目では、`RefMut<i32>`から`&mut i32`を得ています。」

[^deref]: 正確には、`Deref`トレイトや`DerefMut`トレイトを実装している型から`T`を取り出す操作になります。[Derefトレイトでスマートポインタを普通の参照のように扱う - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch15-02-deref.html)

CSS「参照外しの瞬間は所有権とやらは奪われないの？」

Rust「ややこしい部分ですが、型解決のために参照なしの型に一旦戻るだけで、所有権譲渡は発生しません[^copy_move]。」

[^copy_move]: 参照外しで所有権譲渡のようなことが発生しそうなシーンでは、`Copy`トレイトを実装した型でないとコンパイルエラーになると思います。`Copy`トレイトが実装されている場合は、`Clone::clone(&self)`が呼ばれているため、結局所有権自体は不要です。`Copy`トレイトについて詳しくは[おまけ Copyトレイト](#おまけ-copyトレイト)を見てください。

TS「10行目、インクリメントの`*x_mr += 1;`では参照外しを行って`i32`型を得ているけど、`x_mr`から他の変数に所有権が移ったりすることはなさそうだもんね。14行目の`*z.borrow_mut() += 1;`は9行目と10行目を一気に行っている感じ？」

Rust「そうなります。`z.borrow_mut()`は`RefMut<i32>`を返します。`*`を付けて`i32`型として扱い、インクリメントしています。」

CSS「ところでさっきから気になっているんだけど`{`と`}`の中括弧で囲んでインデントしている箇所があるのはなんなの...？」

Rust「スコープを定めるために使用しています。`x_mr`のスコープを狭め、ライフタイムを狭めることで`}`**より外では可変参照が無効になる**ようにしています[^mutref_disable]。ライフタイムについてはまた触れるのでその時解説しますね。」

[^mutref_disable]: この辺も正確にどのように参照が評価されているかを考えるのが難しい部分のため、解説に誤りがある可能性があります。やっぱライフタイムって難しいですね...

TS「無効にならない場合、ランタイム時での借用チェックに失敗しそうだね。最後あたりではあえて可変参照の重複借用を試みているみたいだけど、`z.try_borrow_mut()`というのは...？」

Rust「可変参照として借用中のものであるかを確かめながら、可変参照を得るためのメソッドです。パニックせずに`Result`型にすることで、可変参照がすでに存在する場合には分岐して対応しています。」

TS「`Result`型、冷静に対応できてクールだな...！」

CSS「とりあえず`RefCell`についてはわかった気がする...多分...で、これを結局どう使うのさ？」

Rust「こんな感じで...可変借用したい内側の`Vec<usize>`だけ`RefCell<Vec<usize>>`にすれば...」ｶﾀｶﾀ...

```rust:Rust
use std::cell::RefCell;

fn main() {
    let original_arr: Vec<RefCell<Vec<usize>>> = vec![
        RefCell::new(vec![1, 2, 3]),
        RefCell::new(vec![4, 5, 6])
    ];
    let new_vec: RefCell<Vec<usize>> = RefCell::new(vec![7, 8, 9]);

    let arr: Vec<&RefCell<Vec<usize>>> = original_arr.iter().collect();
    let mut arr2: Vec<&RefCell<Vec<usize>>> = original_arr.iter().collect();

    arr2[1] = &new_vec;

    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);

    (arr2[0].borrow_mut())[0] = 10; // この時点で他に可変参照はない

    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);
}
```

```bash:実行結果
$ rustc main.rs
$ ./main
arr = [RefCell { value: [1, 2, 3] }, RefCell { value: [4, 5, 6] }]
arr2 = [RefCell { value: [1, 2, 3] }, RefCell { value: [7, 8, 9] }]
arr = [RefCell { value: [10, 2, 3] }, RefCell { value: [4, 5, 6] }]
arr2 = [RefCell { value: [10, 2, 3] }, RefCell { value: [7, 8, 9] }]
```

TS「おー！`arr`と`arr2`の型が`Vec<&RefCell<Vec<usize>>>`で一致しているし、」

CSS「`arr`の`println!`出力も可能になっている上に、」

Rust「初見殺しあるあるの実行結果を忠実に再現できていますね。」

TS「シャローコピーによるバグを再現できてここまで感動したのは初めてだよ...」

Rust「しかしまだ"本家"とは少し構造が違います。図にするとこうなっています。」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/1f556593-5ccd-9e03-ccbb-bc11aa2fece2.png)

CSS「...？いやほとんど同じでしょ」

TS「Rustちゃん、こだわるなぁ...」

## ライフタイム制約

- [ライフタイムで参照を検証する - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch10-03-lifetime-syntax.html)

Rust「ポイントはどこから借用しているかです。説明を先延ばしにしていたライフタイムが関わる話ですが、**`arr`と`arr2`は、貸し出し主である`original_arr`と`new_vec`が生きている間しか存在できません**。具体的には、次のようなコードが書けません。」ｶﾀｶﾀ...

```rust:Rust(コンパイルエラー)
use std::cell::RefCell;

fn main() {
    let arr: Vec<&RefCell<Vec<usize>>>;
    let mut arr2: Vec<&RefCell<Vec<usize>>>;

    {
        let original_arr: Vec<RefCell<Vec<usize>>> = vec![
            RefCell::new(vec![1, 2, 3]),
            RefCell::new(vec![4, 5, 6])
        ];
        let new_vec: RefCell<Vec<usize>> = RefCell::new(vec![7, 8, 9]);

        arr = original_arr.iter().collect();
        arr2 = original_arr.iter().collect();

        arr2[1] = &new_vec;

        println!("arr = {:?}", arr);
        println!("arr2 = {:?}", arr2);
    
        (arr2[0].borrow_mut())[0] = 10;
    } // original_arrとnew_vecはここでドロップ

    println!("arr = {:?}", arr); // 貸し出し主不在なので不正な参照になりエラー
    println!("arr2 = {:?}", arr2);
}
```

```bash:エラー
$ rustc main.rs
error[E0597]: `original_arr` does not live long enough
  --> main.rs:14:15
   |
14 |         arr = original_arr.iter().collect();
   |               ^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
23 |     }
   |     - `original_arr` dropped here while still borrowed
24 |
25 |     println!("arr = {:?}", arr);
   |                            --- borrow later used here

error[E0597]: `new_vec` does not live long enough
  --> main.rs:17:19
   |
17 |         arr2[1] = &new_vec;
   |                   ^^^^^^^^ borrowed value does not live long enough
...
23 |     }
   |     - `new_vec` dropped here while still borrowed
...
26 |     println!("arr2 = {:?}", arr2);
   |                             ---- borrow later used here

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
```

Rust「先ほども少しだけ登場しましたが、中括弧`{`と`}`はその変数を使えるスコープを定め、さらにリソースの**ライフタイム**(=生存期間)も限定します。**リソースの生存期間が本家の`arr`と`arr2`とは異なっている**ので、本家とはまだ違うと言いました。」

CSS「こだわりが最早ワガママレベル...(目的は達成できてるしもう良くないか...？続けるの...？って思った読者は[あとがき](#あとがき)に行っちゃっていいと思うよ...)」

TS「うーんと、この場合...`original_arr`と`new_vec`がスコープ外で使えないのは私と一緒だね。ライフタイムというのが...イマイチピンと来ない...貸し出し主本人に会えないのに貸し続けてもらうわけにはいかない、みたいな？」

Rust「ここは例え話ではなく私とTSさんの"違い"を明らかにした方がわかりやすいかと。」

違い...？Rustちゃんは何ともなしに言ったけど、何故か身体が強張ってしまった。

CSS「いやここまでずっと違いしか見てこなかったじゃんwww」

Rust「ああいえ、すみません。TSさんとの違いというよりは私独特の性質なんですが」

CSS「...ふざけて言ってる...？それとも天然で言っているのか...？」

TS「結局"違い"とは...？」

食い気味に聞いてしまった

Rust「私...**ガベージコレクタを持っていない**んです。」

TS「使わなくなったメモリ領域を自動でお掃除してくれるあの機能...？」

Rust「そうです。無いって言うと不正確かもしれませんが...**私自身が自分でメモリを片付けています**。」

TS「えぇー？！その神業ができるのってC言語先生やC++先生ぐらいだと思ってた...」

Rust「姉の...C++の話は苦手なので避けていただけると...」

CSS「そもそも姉妹なの？！全く気付かなかった...」

Rust「義理ですがね。それに姉のは神業でもなんでもなく姉がズボラなだけです。」

TS「先生相手に結構ズタボロに言うね...ところで、じゃあどうやって"お掃除"してるの？」

Rust「基本的には、リソースの所有権を持つ変数がスコープ終端まで着いたら、そのリソースは片付けています。リソースが生成されてからこの片付けられるまでの期間を、ライフタイムと呼んでいます。4番目の制約として紹介していた通り、リソースへの参照もライフタイムより長くは生きられません。」ｶﾀｶﾀ...

```rust:Rust
fn main() {
    let x: i32 = 1;
    let mut p: &i32 = &x;

    println!("x = {}, p = {}", x, p);

    {
        // ここで宣言しているyはスコープ外からは参照できない
        let y: i32 = 2; // #### yのライフタイムはここから
        p = &y; // yが生きているので&yをpに代入できる

        println!("x = {}, y = {}, p = {}", x, y, p); // xはここからでも参照可能

    } // ここでyを片付ける。#### yのライフタイムはここまで。&yも消失

    // pの中身である&yは無効な参照になっているのでここでの出力はコンパイルエラー
    // println!("x = {}, p = {}", x, p);

    p = &x; // xはまだ生きている

    println!("x = {}, p = {}", x, p);

} // ここで全てのリソースが解放される
```

CSS「スコープの終端って中括弧の終わり(`}`)のことか。さっきからリソース操作のために`{`や`}`が登場していたんだな。」

TS「そして**所有権を気にしているのは片付ける時に困るから**だったんだね...なるほど...」

所有権とライフタイムは、Rustちゃん流の片付け術、といったところなのだろう。

Rust「TSさんのコードではおそらく、**配列への参照が残っている限り**`arr`や`arr2`の参照先は片付けられずに残っているはずです。同様の仕組みを提供する打って付けの型があるので、それを使って書き直せば完成になります。」

TS「"マジ"でこだわってますね...そこまでリソースについて考えたことないや」

CSS「("マジ"でこだわってますね...？)」

## `Rc`

Rust「こだわり実現のため、スコープの終端ではなく、**すべての参照がなくなった時に**リソースを解放するスマートポインタ `Rc`を使います。RcはReference Counter、和訳すると参照カウンタの略です。`Rc`は`Deref`トレイトを実装しており**不変参照のように**扱えます。」ｶﾀｶﾀ...

- [Rcは、参照カウント方式のスマートポインタ - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch15-04-rc.html)
- [Derefトレイトでスマートポインタを普通の参照のように扱う - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch15-02-deref.html)

```rust:Rust
#[derive(Debug)]
struct Hoge;

impl Hoge {
    fn use_ref(&self) {
        println!("called use_ref: {:?}", self);
    }
}

impl Drop for Hoge {
    fn drop(&mut self) {
        println!("Hoge is dropped");
    }
}

use std::rc::Rc;

fn main() {
    println!("Program start");
    {
        let joge: Rc<Hoge>;
        {
            let ioge: Rc<Hoge>;
            {
                // 初めてのリソース確保
                let hoge: Rc<Hoge> = Rc::new(Hoge); // カウント1
                ioge = Rc::clone(&hoge); // ++カウント == 2

                println!("{:?} hoge is dropping.", hoge); // --カウント == 1
            }
            // Rc::clone(&hoge)と同じ
            joge = ioge.clone(); // ++カウント == 2

            println!("{:?} ioge is dropping.", ioge); // --カウント == 1
        }

        joge.use_ref(); // RcはDerefトレイトを実装しているのでRc<Hoge>は&Hogeとして使える

        println!("{:?} joge is dropping.", joge); // --カウント == 0
    } // ここでHogeがdropされる
    println!("Program end");
}
```

```bash:実行結果
Program start
Hoge hoge is dropping.
Hoge ioge is dropping.
called use_ref: Hoge
Hoge joge is dropping.
Hoge is dropped
Program end
```

Rust「上記の例では、私がリソースを破棄(drop)する際の挙動を実装できる`Drop`トレイトを利用して、参照がすべて消滅した際にリソースが片付けられていることを確認しています。」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/c636ada4-bcc7-561a-774f-f8b8f9e3aacc.png)

Rust「`hoge`、`ioge`、`joge`の型がすべて`Rc<Hoge>`である点がポイントです。`Rc`によるリソース管理では『貸し出し主』と『借用』のような上下関係、貸借関係はなく、参照自体がリソース管理の鍵となっています。」

CSS「貸借関係がない...さっきで言うと貸し出し主の`original_arr`や`new_vec`が要らなくなるわけだ。」

Rust「はい。登場する変数は対等にリソースを参照しています。このように別な見方として、しばしば**所有権を複数で共有する**ために使われるスマートポインタ、だと紹介されます。」

TS「挙動については、図を見た感じ、`Rc::clone`関数[^rc_clone]で**参照だけコピーしている**みたい！これって、初見殺しあるあるで元々実現したかったシャローコピーの挙動だね。」

[^rc_clone]: 本当は`Rc`型に実装された`Clone`トレイト由来のメソッド`clone`で、コード中にも書いたように`Rc`型の変数について`hoge.clone()`のように呼び出すことも可能です。一般的な`clone`メソッドではリソースのクローンが行われるコストがかかる一方、こちらは参照のみクローンされコストがかかりません。それを区別するため、慣例的に関連関数のように呼び出す文化があるそうです。その文化に合わせました。

Rust「実はこだわりたかった理由は『参照だけコピー』という雰囲気を出したいからというのもありました。ではいよいよ、`Rc`を使ってあるあるを実現してみますね」ｶﾀｶﾀ...

TS「いよいよだね！緊張する...」ﾄﾞｷﾄﾞｷ...

```rust:Rust
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let arr: Vec<Rc<RefCell<Vec<usize>>>> = vec![
        Rc::new(RefCell::new(vec![1, 2, 3])),
        Rc::new(RefCell::new(vec![4, 5, 6])),
    ];
    // ↓cloneメソッドが再帰的に呼ばれる。Rcのcloneは参照だけコピー
    let mut arr2: Vec<Rc<RefCell<Vec<usize>>>> = arr.clone();

    arr2[1] = Rc::new(RefCell::new(vec![7, 8, 9]));

    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);

    (arr2[0].borrow_mut())[0] = 10;

    println!("arr = {:?}", arr);
    println!("arr2 = {:?}", arr2);
}
```

```bash:実行結果
$ rustc main.rs
$ ./main 
arr = [RefCell { value: [1, 2, 3] }, RefCell { value: [4, 5, 6] }]
arr2 = [RefCell { value: [1, 2, 3] }, RefCell { value: [7, 8, 9] }]
arr = [RefCell { value: [10, 2, 3] }, RefCell { value: [4, 5, 6] }]
arr2 = [RefCell { value: [10, 2, 3] }, RefCell { value: [7, 8, 9] }]
```

CSS「実行結果はちゃんと初見殺しあるあるとおんなじだ」

TS「変数が減った分、さっきよりすっきりしたね！」

Rust「リソースのライフタイムは`arr`と`arr2`両方が消えるまでになっています。図に描き起こすと...」ﾎﾜｲﾄﾎﾞｰﾄﾞｶｷｶｷ...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205472/50049f0a-4b73-e5a6-78c2-f2bb677ea533.png)



TS「無事、初見殺しあるあるを描き写した感じになったね！」

# エピローグ

もうすでに外は真っ暗で、いつもの委員会活動ならとっくに家に帰っているような時刻になっていた。

TS「しっかしシャローコピーの実装だけにこんなに時間がかかるとは思わなかったよ...」

Rust「TSさんが伝えたかった処理をソースコードとして書けて、私にとってもとても勉強になりました。」

CSS「なんで私まで...なんてね。Rustちゃんのことよくわかった気がするし、2人が仲良くなれたみたいで良かった良かった。」

TS「なんか気恥ずかしいな...ハハハ...それにしても最後に書いたコードも大分読むのが大変そうな見た目だったよね。いつもあんななの？」

Rust「いえ、『**あんな変なこと**』は普段しないので...`Rc`や`RefCell`が必要になることは滅多にないですね。」

TS「へん...(涙)」

CSS「あー！またTSちゃんを落ち込ませて！Rustちゃん...そういうとこだぞ...」

Rustちゃんこそ変なところで堅いし、何考えているかよくわからないし、でも実はすごいところがあったりして...そんな秘密を知ることができて、今日はとても楽しい一日でした！

～ fin ～

# あとがき

本小説は、前回出した記事中の「TypeScriptとRustがペアプロする物語が書きたい！」という思いをこらえきれず具現化したものになります。

https://qiita.com/namn1125/items/8ed4d91d3d00af8750f8

小説スタイルで技術的な話をするのは、結構難しい部分が多かったです。

- 話の文脈を断ち切りどうしても伝えたいことを書く、というわけにいかない
- 目次やまとめが入れにくい
- **最後まで読んでもらわないと何を伝えたかったかが伝わらない**
- **そもそも伝えたいことをストレートに伝えるのが難しい**
- ~~推敲が難しすぎる~~

...というわけでこの位置になってしまったことを後悔しつつ、記事で**伝えたかったこと**を書きます。

:::note info
**伝えたかったこと**

Rustは所有権やスマートポインタのおかげで**シャローコピーのような複雑な構造は記述が目立つ**ようにできており、**良くない構造が書きにくくなっている**。

所有権やスマートポインタといった仕組みは最適化のために科せられた**必要悪ではなく**、**変な設計をしないための積極的な防御策であり**、味方につけるととても心強い
:::

「良くない構造が書きにくい」というのは、裏を返すと「書きやすい構造は良い構造である」ということで、そこを前半の「Rustの`clone`はデフォルトでディープコピーである」のところで表現したつもりでした。

後半のRustちゃんがムッっとなって可変参照やスマートポインタを使って無理やりシャローコピーを実現したパートでは、本当に伝えたかったのは上述の通り「Rustでは下手な構造はそもそも書きにくくなっている」ということだったのですが、変に「Rustはやっぱり難しい言語...」という印象をつけてしまったかもしれず、ちょっとだけ後悔しています。ﾄﾞｸｼｬｻﾏﾄﾞｳｶｻｲｺﾞﾉｱﾄｶﾞｷﾏﾃﾞﾖﾝﾃﾞｸﾀﾞｻｲﾏｽﾖｳﾆ...

伝えたいメッセージが少ない記事ならばやめ太郎さんのように対話型で書くのは効果的かもしれませんが、小説スタイルで書かれた記事があんまりない理由は今回身に染みてわかりました(苦笑)。次回記事はまた普通の書き方をしていると思います。多分。

ここまで読んでくださり誠にありがとうございました！！

2023/07/19 追記

RustではなくReactが題材ですが、[続き](https://qiita.com/namn1125/items/d420ae48c19a3d7c8248)を書きました！読んでいただけたら幸いです。

https://qiita.com/namn1125/items/d420ae48c19a3d7c8248

# おまけ `Copy`トレイト

- [Copy in std::marker - Rust](https://doc.rust-lang.org/std/marker/trait.Copy.html)

本来は`Clone`トレイトにて一緒に説明するべきトレイトだったのですが、尺の都合上？説明できなかったためおまけに掲載させていただきます。

`Copy`トレイトは簡単に説明すると、「本来は所有権譲渡が行われる場所・書き方で、クローンしないとエラーになる場所について、~~**自動で`.clone()`が付いていたことにしてくれる**~~ **暗黙クローンしてくれるようになる** マーカートレイト」です。

:::note warn
`Clone` トレイトをderiveを使わずに手動実装したとして、 `Copy` トレイトを付与して暗黙クローンを行う際、 **別に `.clone()` が呼ばれるわけではない** ようなので上記記述を編集いたしました。以降の記述もそれに伴い編集するべきかもしれませんが、覚え方として大筋は間違っていないと考えているため、そのままにします[^clonewrong]。

(2024/06/26 追記)
:::

[^clonewrong]: `Clone`トレイトの手動実装がヘンテコな実装(副作用を引き起こすなど)になっている際は本記事の説明は嘘になります。しかしそもそも `clone` メソッドはなるべくderiveにより実装されるべきで、仮に手動実装している場合は同時に `Copy` トレイトを付与しているのが([可能でありますが](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=926f5ee8f4dea590e5a1b5f9a6f54eb0))おかしいです。通常用途の範囲では嘘はついてないと思います(要出典な部分は多いですが...)。

例を示します。所有権譲渡のため以下はエラーでした。

```rust:Rust(コンパイルエラー)
#[derive(Debug, Clone)]
struct Hoge {
    v: Vec<usize>
}

fn main() {
    let hoge = Hoge { v: vec![1, 2, 3] };
    let hoge2 = hoge; // 所有権譲渡のためエラー！
    println!("{:?}", hoge);
    println!("{:?}", hoge2);
}
```

[`Clone`トレイトの節](#rustの所有権とcloneトレイト)では複製により所有権譲渡が発生しないという`clone`メソッドを用いた解決方法を提示しました。(`#[derive(Clone)]`と書くことで構造体に`Clone`トレイトが自動実装されています。)

```diff_rust:Rust
#[derive(Debug, Clone)]
struct Hoge {
    v: Vec<usize>
}

fn main() {
    let hoge = Hoge { v: vec![1, 2, 3] };
-    let hoge2 = hoge;
+    let hoge2 = hoge.clone();
    println!("{:?}", hoge);
    println!("{:?}", hoge2);
}
```

しかし、使用するメモリ領域が小さく、いちいち`clone`を呼ぶ方が手間だと感じるような構造体もたまにはあるでしょう。`Copy`トレイトはそんなときに使えます。

```rust:Rust
#[derive(Debug, Clone, Copy)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 1, y: 2 };
    let p2 = p; // 裏ではp.clone()となっている。
    println!("{:?}", p);
    println!("{:?}", p2);
}
```

注目してほしいのは`#[derive(Debug, Clone, Copy)]`の`Copy`です。`#[derive(Copy)]`とすることでこの`Copy`トレイトが実装され、`.clone()`を省略しても所有権譲渡の場面では勝手に複製されるようになります。

ところで何故`Clone`トレイトと`Copy`トレイトが分かれているのでしょうか？`Clone`トレイトだけでは自動でクローンしてくれないのはなぜなのでしょう？これは**リソースの複製というコストがかかる操作がどこで行われているかが、ソースコードを読めばすぐ分かるようにするため**です。`Copy`トレイトをあえて実装しないことで、`clone`メソッドを明記しなければならず、そこがコストがかかる箇所だとすぐわかるようになっています。

```rust:Rust
fn main() {
    let s = String::from("hoge");

    // 参照を取るだけ。軽そう
    let v1 = (0..10).map(|_| &s).collect::<Vec<_>>();

    // .clone()が呼ばれてる？！重そう！！！
    let v2 = (0..10).map(|_| s.clone()).collect::<Vec<_>>();
}
```

この考えに則れば、`Copy`トレイト付与を乱用するのは避けるべきということがわかるでしょう。

以下、deriveマクロによる`Clone`トレイトと`Copy`トレイト付与のために求められる構造体の条件です。

- `Clone`トレイト
    - 構造体が持つすべてのフィールドの型が`Clone`トレイトを実装していること
- `Copy`トレイト
    - 構造体自体が`Clone`トレイトを実装していること
    - 構造体が持つすべてのフィールドの型が`Clone`トレイトと`Copy`トレイトを共に実装していること

よく「プリミティブ型は所有権譲渡が発生しないけど構造型や文字列型、ベクタ型は所有権譲渡が発生する」といった解説を目にしますが、これは事実としては合っていますがあまり的を射ていません。「所有権譲渡が発生しないとされるプリミティブ型」の[公式ドキュメント](https://doc.rust-lang.org/std/primitive.i32.html)に行ってみると、[Copyトレイトが実装されている](https://doc.rust-lang.org/std/primitive.i32.html#impl-Copy-for-i32)のを確認できるはずです。すなわち「`Copy`トレイトが実装された型は勝手に複製され所有権譲渡が発生しない」と説明したほうがより一般的な解説になっています。

# 参考・引用

- [変数宣言: letとconst | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/values-types-variables/let-and-const)
- [オブジェクト型のreadonlyプロパティ (readonly property) | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/values-types-variables/object/readonly-property)
- [参照と借用 - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch04-02-references-and-borrowing.html)

# 実行環境

```bash:bash
$ ts-node --version
v10.9.1
$ npm ls -g typescript
/usr/local/lib
├─┬ ts-node@10.9.1
│ └── typescript@5.0.4
└── typescript@5.0.4
$ cargo --version
cargo 1.68.2 (6feb7c9cf 2023-03-26)
```