[Rust] チュートリアル④　CargoとCrates.io〜循環参照まで

# はじめに
Rustのチュートリアルのメモです④。


# リンク集

[C++入門](https://amzn.to/2Nf1ntW)
[プログラミングRust (日本語) ](https://amzn.to/2Bs7vvS)
[プログラミング言語Rust入門](https://amzn.to/2BkGP0n)
[実践Rust入門](https://amzn.to/2zRbu4W)

[std::検索](https://doc.rust-lang.org/stable/std/)


# CargoとCreates.io

- リリースプロファイルでビルドをカスタマイズ
- creates.ioでライブラリを公開する
- ワークスペースで巨大なプロジェクトを体系化する
- creates.ioからバイナリをインストールする
- 独自のコマンドを使用してCargoを拡張する


## リリースプロファイルでビルドをカスタマイズする

```
// devプロファイル (開発用)
cargo build

// releaseプロファイル (リリース用)
cargo build --releaseプロファイル
```

Cargo.tomlファイルに[profile.*]セクションが存在しない際に適用される各プロファイル用のデフォルト設定が、Cargoには存在する

カスタマイズしたいプロファイル用の[profile.*]セクションを追加することで、デフォルト設定の一部を上書きすることができる

```
[profile.dev]
opt-level=0 // コンパイル時間が短い

[profile.release]
opt-level=3 // 長い
```


## Crates.ioにクレートを公開

///でドキュメンテーションコメントできる
Markdown記法もサポートしている


```rust
/// Adds one to the number given.
/// 与えられた数値に1を足す。
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}
```

```terminal: 現在のクレートドキュメント用のHTMLを構築し、おｓの結果をWebブラウザで開く
cargo doc --open
```

### その他、省略


## Cargoのワークスペース

プロジェクトの開発が進むにつれて、ライブラリクレートの肥大化が続き、その上で複数のライブラリクレートにパッケージを分割したくなる
この場面において、Cargoはワークスp−エスという強調して開発された関連のある複数のパッケージを管理するのに役立つ機能を提供している


### ワークスペースを生成する

ワークスペースは、同じCargo.lockと出力ディレクトリを共有する一連のパッケージ
ワークスペースを使用したプロジェクトを作成し、ワークスペースの構造に集中できるよう、瑣末なコードを使用する
一般的にはバイナリ１つとライブラリ２を含むワークスペースをつくる

```
mkdir add
cd add
```

```Cargo.toml
[workspace]

members = [
	"adder",
]
```

addディレクトリ内でcargo new を実行することでadderバイナリクレートを作成する

```:作成されたadderバイナリクレートのディレクトリツリー
├── Cargo.lock
├── Cargo.toml
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target
```

```
$ cargo new add-one --lib
     Created library `add-one` project
```

```
├── Cargo.lock
├── Cargo.toml
├── add-one
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target
```

```rust:add-one/src/lib.rs

pub fn add_one(x: i32) -> i32 {
	x + 1
}
```


#### failed to read cargo.tomlと警告文がでるとき

[package]にpathを追加する

```Cargo.toml
[package]
path = "src/main.rs"
```


ワークスペースにライブラリクレートが存在するようになったら、バイナリクレートadderをライブラリクレートのadd-oneに依存させられる
まず、add-oneへのパス依存をadder/Cargo.tomlに追加する

```rust:adder/Cargo.toml

[dependencies]

add-one = { path = "../add-one" }

```

```rust: adder/src/main.rs

// add-oneクレートを使う
extern crate add_one;

fn main() {
	let num = 10;
	println!("{}", add_one::add_one(num));
}
```


```:実行したいパッケージを指定して実行
cargo run -p adder
```


Cargo.lockはワークスペースに１つだけ存在する (cargo buildはワークスペースの最上位階層で実行するので)

### ワークスペースの外部クレートに依存する

```add-one/Cargo.toml
[dependencies]

rand = "0.3.14"
```

randはワースくペースのどこかで使用されているにもかかわらず、それぞれのCargo.tomlファイルにも、randを追加しない限り、ワークスペースの他のクレートでそれを使用することは出来ない

```:Cargo.tomlに記載のないクレートでrandを使用とするとcargo buildでエラーとなる

error[E0463]: can't find crate for `rand`
 --> adder/src/main.rs:2:1
  |
2 | extern crate rand;
  | ^^^^^^^^^^^^^^^^^^ can't find crate
  ```

他のクレートで使用するためにCargo.tomlにrandを追記してbuildすれば使用できるようになる
これによりrandのファイルが追加でダウンロードされることはない
Cargoが、ワークスペースのrandを使用するどのクレートも、同じバージ ョンを使っていることを確かめてくれる
ワークスペース全体でrandの同じバージョンを使用することにより、複数のコピーが存在しないのでスペースを節約し、ワークスペースのクレートが相互に互換性を維持することがdケイル


## 独自のコマンドでCargoを拡張する

$PATHにあるバイナリがcargo-somethingという名前ならcargo somethingを実行することで、Cargoのサブコマンドであるかのうように実行することができる


```:cargo 〇〇 のようなサブコマンドの一覧を表示
cargo --list
```


# スマートポインタ

Rustで最もありふれた種類のポインタは、参照
参照は&で示唆され、指している値を借用する
データを参照すること以外に特別な能力は何もない
オーバーヘッドもなく、最も頻繁に使われる種類のポインタ

スマートポインタは、ポインタのように振る舞うだけでなく、追加のメタデータと能力があるデータ構造
スマートポインタの概念はRust特有のものではない
C++に端を発し、他の言語にも存在している
Rustでは、標準ライブラリに定義された様々なスマートポインタが、参照以上の機能を提供する
その１つの例が、参照カウント方式のスマートポインタ
このポインタにより、所有者の数を追いかけることでデータに複数の所有者をもたせることができ、所有者がいなくなったら、データの片付けをする

所有権と借用の概念を使うRustで、参照とスマートポインタの別の差異は、参照はデータを借用するだけのポインタであること
対象的に多くの場合、スマートポインタは指しているデータを所有する

StringやVec<T>のように、メモリを所有し、それを弄ることができるので、スマートポインタに数えられる

また、メタデータ（キャパシティなど) や追加の能力、あるいは保証(Stringならデータが常に有効なUTF-8であることを保証するなど)もある

スマートポインタは普通、構造体を使用して実装されている
スマートポインタを通常の構造体と区別する特徴は、スマートポインタは、DerefとDropトレイトを実装していること

Derefトレイトにより、スマートポインタ構造体のインスタンスは、参照のように振る舞うことができるので、参照あるいはスマートポインタのどちらとも動作するコードを書くことができる

Dropトレイトにより、スマートポインタのインスタンスがスコープを外れた時に走るコードをカスタマイズすることができる

多くのライブラリに独自のスマートポインタがあり、自分だけのスマートポインタを書くことさえできる
標準ライブラリの最もありふれたスマートポインタを学ぶ

- ヒープに値を確保するBox<T>
- 複数の所有権を可能にする参照カウント型のRc<T>
- RefCall<T>を通してアクセスされ、コンパイル時ではなく実行時に借用規則を強制する型のRef<T>とRefMut<T>

さらに、不変な型が、内部の値を可変化するAPIを晒す内部可変性パターンについて
また循環参照について、これによってメモリがリークする方法と回避方法


## ヒープのデータを指すBox<T>を使用する

最も素直なスマートポインタはボックスであり、その型はBox<T>と記述される
ボックスにより、スタックではなくヒープにデータを格納することができる
スタックに残るのは、ヒープデータへのポインタ

- コンパイル時にはサイズを知ることが出来ない型があり、正確なサイズを要求する文脈でその方の値を使用する時
- 多くのデータがあり、所有権を転送したいが、その際にデータがコピーされないようにしたい時　
 - 多くのデータの所有権を転送するには、データがスタック上でコピーされるので、長い時間がかかり得る、この場合でパフォーマンスを向上させるには、多くのデータをヒープ上にボックスとして格納する
- 値を所有する必要があり、特定の型ではなく特定のトレイトを実装する型であることのみ気にかけている時


### Box<T>を使ってヒープにデータを格納する

```rust
// bがmainの終わりでするようにボックスがスコープを抜けたら、メモリから解放される
fn main(){
	let b = Box::new(5);
	println!("b={}", b);
}
```

メモリの解放はボックスと指しているデータに対して起きる
(スタックに格納されているポインタと、ヒープに格納されているデータ)


### ボックスで再帰的な方を可能にする

コンパイル時に、コンパイラは、ある方が取る領域を知る必要がある
コンパイル時にサイズがわからない方の１つ、再帰的な型であり、これは、型の１部として同じ型の他の値を持つもの

この値のネストは、理論的には無限に続く化膿性があるので、コンパイラは再帰的な型の値が必要とする領域を知ることができない
しかしながら、ボックスは既知のサイズなので、再帰的な型の定義にボックスを挟むことで再帰的な型を存在させることができる


### コンスリスト

コンスリストは関数型プログラミングでは一般的なデータ型
これを再帰的な型の例として探求する

Lisp(list processing)プログラミングとその方言に由来するデータ構造
Lispでは、cons関数(construct function)が２つの引数から新しいペアを構成し、この引数は通常、単独の値と別のペアからなる
これらのペアを含むペアがリストをなす

コンスリストの各要素は、２つの要素を含む
現在の要素の値と次の要素
リストの最後の要素は、次の要素なしにNilと呼ばれる値のみを含む(nullやnilの概念とは異なる)

```rust

// 再帰的なenumを定義しようとするとエラーになる
// 自身の別の値を直接保持しようとしたため
// 結果として、コンパイラは、List値を格納するのに必要な領域が計算できない
enum List {
	Cons(i32, List),
	Nil,
}

use List::{Cons, Nil};

fn main() {
	// 無限のCons列挙子からなる無限のList
	let list = Cons(1, Cons(2, Cons(3, Cons(4, Nil))));
}

// output
error[E0072]: recursive type `List` has infinite size
 --> src/main.rs:1:1
  |
1 | enum List {
  | ^^^^^^^^^ recursive type has infinite size
2 |     Cons(i32, List),
  |               ---- recursive without indirection
  |
  = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
```

```:提言：間接参照」で、値を直接格納する代わりに、データ構造を変更して値へのポインタを変わりに格納することで、値を間接的に格納する
  = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
```


```rust
// ConsがBoxを保持しているので、無限にサイズがあるわけではないのでコンパイルが通る

enum List {
	Cons(i32, Box<List>),
	Nil,
}

use List::{Cons, Nil};

fn main() {
	let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
```


## Derefトレイトでスマートポインタを普通の参照のように扱う

Derefトレイトを実装するｋとで参照外し演算子の*の振る舞いをカスタマイズすることができる
スマートポインタを普通の参照のように扱えるようにDerefを実装することで、参照に対して処理を行うコードを書き、そのコードをスマートポインタとともに使用できる

```rust
fn main() {
	let x = 5;
	let y = &x;
	assert_eq!(5, x);
	assert_eq!(5, y); //  yは参照なので、値と比較出来ずエラーとなる
}

// output

error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src/main.rs:5:2
  |
5 |     assert_eq!(5, y);
  |     ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
  |
  = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for `{integer}`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


fn main() {
	let x = 5;
	// xの値の参照ではない
	// xの値を指すボックスのインスタンスにyをセットしている
	let y = Box::new(x);
	assert_eq!(5, x);
	assert_eq!(5, y);
}

// output 

error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src/main.rs:5:2
  |
5 |     assert_eq!(5, y);
  |     ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
  |
  = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for `{integer}`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


 fn main() {
	let x = 5;
	// xの値の参照ではない
	// xの値を指すボックスのインスタンスにyをセットしている
	let y = Box::new(x);
	assert_eq!(5, x);
	assert_eq!(5, *y); // 参照外しでxの値を指す
} 

// output
エラーなし
```


### 独自のスマートポインタを定義する

標準ライブラリが提供しているBox<T>型に似たスマートポインタを構築して、スマートポインタは規定で参照に比べてどう異なるのかを経験する

Box<T>型は究極的に1要素のタプル構造体として定義されている

```rust

struct MyBox<T>(T);

impl<T> MyBox<T> {
	fn new(x: T) -> MyBox<T> {
		MyBox(x)
	}
}

fn main() {
	let x = 5;
	let y = MyBox::new(x);

	assert_eq!(5, x);
	assert_eq!(5, *y);
}

// output
error[E0614]: type `MyBox<{integer}>` cannot be dereferenced
  --> src/main.rs:14:16
   |
14 |     assert_eq!(5, *y);
   |                   ^^

error: aborting due to previous error
```

Box<T>と同じようにMyBox<T>を使おうとすると、参照外しできないとエラーになる


### Derefトレイトを実装して型を参照のように扱う

### Derefトレイトを実装して型を参照のように扱う

トレイトを実装するには、トレイトの必須メソッドに実装を提供する必要がある

```rust
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> Deref for MyBox<T> {
	// Derefトレイトが使用する関連型を定義している
	type Target = T;

	// selfを借用し、内部のデータへの参照を返す
	fn deref(&self) -> &T {
		&self.0
	}
}

impl<T> MyBox<T> {
	fn new(x: T) -> MyBox<T> {
		MyBox(x)
	}
}

fn main() {
	let x = 5;
	let y = MyBox::new(x);

	assert_eq!(5, x);
	assert_eq!(5, *y); // 水面下でコンパイラは*(y.deref())を実行している
}
```

derefメソッドが値への参照を返し、*(y.deref())のカッコの外の何の変哲もない参照外しがそれでも必要な理由は、所有権システム

derefメソッドが値への参照ではなく、値を直接返したら、値はselfから外にムーブされてしまう
今回の場合や、参照外し演算子を使用する多くの場合にはMyBox<T>の中の値の所有権を奪いたくない
　

## Dropトレイトで片付け時にコードを走らせる

スコープを抜けそうになった時に起こることをカスタマイズできる
どんな型に対してもDropトレイトの実装を提供することができ、指定したコードは、ファイルやネットワーク接続などのリソースを解放するのに活用できる
Dropトレイトの機能は、ほぼ常にスマートポインタを実装する時に使われている
Box<T>はDropをカスタマイズしてボックスが示しているヒープの領域を開放している

ある言語では、プログラマがスマートポインタのインスタンスを使い終わるたびにメモリやリソースを解放するコードを呼ばなkればならない
忘れてしまったら、システムは詰め込み過ぎになりクラッシュする可能性がある
Rustでは、値がスコープを抜けるたびに特定のコードが走るように指定でき、コンパイラはこのコードを自動的に挿入する
結果として、特定の型のインスタンスを使い終わったプログラムの箇所全部にクリーンアップコードを配置するのに配慮する必要はない
それでもリソースをリークすることはない


## Rc<T>は、参照カウント方式のスマートポインタ

複数の所有権を可能のにするため、RustにはRc<T>を使う
reference counting(参照カウント)
Rc<T>型は、値がまだ使用中かどうか決定する値への参照の数を追跡する
値への参照が０なら、どの参照も無効にすることなく、値は片付けられる


### Rc<T>でデータを共有する

```rust:失敗
	enum List {
	Cons(i32, Box<List>),
	Nil,
}

use List::{Cons, Nil};

fn main() {
	let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
	let b = Cons(3, Box::new(a));
	// aはbにムーズ済みなため、再びaをムーブすることはできない
	let c = Cons(4, Box::new(a));
}

// compile
error[E0382]: use of moved value: `a`
  --> src/main.rs:12:27
   |
9  |     let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
   |         - move occurs because `a` has type `List`, which does not implement the `Copy` trait
10 |     let b = Cons(3, Box::new(a));
   |                              - value moved here
11 |     // aはbにムーズ済みなため、再びaをムーブすることはできない
12 |     let c = Cons(4, Box::new(a));
   |                              ^ value used here after move
```

```rust:成功
use std::rc::Rc;

enum List {
	Cons(i32, Rc<List>),
	Nil,
}

use List::{Cons, Nil};

fn main() {
	// List列挙子を使う前に初期化処理に含まれていないので、use文を追加して、Rc<T>をスコープに導入する必要がある
	let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
	// Rc::cloneの呼び出しは、参照カウントをインクリメントするだけであり、時間はかからない
	// 参照カウントにRc::cloneを使うことで、視覚的にディープコピーをするたぐいのクローンと参照カウントを増やす種類のクローンを区別することができる
	let b = Cons(3, Rc::clone(&a)); // aの参照カウント2
	let c = Cons(4, Rc::clone(&a)); // aの参照カウント3
}
```


### Rc<T>を参照数を確認する

```rust
fn main() {
	let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
	// a生成後のカウント = {}
	println!("count after creating a = {}", Rc::strong_count(&a));
	let b = Cons(3, Rc::clone(&a));
	// b生成後のカウント = {}
	println!("count after creating b = {}", Rc::strong_count(&a));
	{
		let c = Cons(4, Rc::clone(&a));
		// c生成後のカウント = {}
		println!("count after creating c = {}", Rc::strong_count(&a));
	}
	// cがスコープを抜けた後のカウント = {}
}

//output
count after creating a = 1
count after creating b = 2
count after creating c = 3
```


## RefCell<T> と内部可変パターン

内部可変性は、そのデータへの不変参照がある時でさえもデータを可変化できるRustでのデザインパターン
普通、この行動は借用規則により許可されていない


### ReCell<T>で実行時に借用規則を強制する

Rc<T>と異なり、RefCell<T>型は、保持するデータに対して単独の所有権を表す
なぜ、RefCell<T>がBox<T>のような型と違うのか

- いかなる時も(以下の療法でなく,)1つの可変参照かいくつもの不変参照のどちらかが可能になる
- 参照は常に有効でなければならない

参照とBox<T>では、借用規則の不変条件は、コンパイル時に強制されている
RefCell<T>では、これらの不変条件は、実行時に強制される

参照でこれらの規則を破ったら、コンパイルエラーになる
RefCell<T>でこれらの規則を破ったら、プログラムはパニックし、終了する

多くの場合でコンパイル時に借用規則を精査することが最善の選択肢であり、これがRustの規定になっている

借用規則を実行時に変わりに精査する利点は、コンパイル時の精査では許容されない特定のメモリ安全な筋書きが許容されること
Rustコンパイラのような静的解析は、本質的に保守的
コードの特性には、コードを解析するだけでは検知できないものもある
最も有名な例は停止性問題

不可解な分析もあるので、Rustのコンパイラが、コードが所有権規則に応じていると確証を得られない場合、正しいプログラムを拒否する可能性がある
コードが借用規則に従っているとプログラマは確証を得ているがコンパイラがそれを理解し保証することが出来ない時にRefCell<T>型は有用

- Rc<T>は、同じデータに複数の所有者を持たせている
- Box<T>とRefCell<T>は単独の所有者
- Box<T>では、不変借用も可変借用もコンパイル時に精査できる
- RefCell<T>は実行時に精査される可変借用を許可するので、RefCell<T>が不変でもRefCell<T>内の値を可変化できる



```rust:コンパイルできない
pub trait Messenger {
	fn send(&self, msg: &str);
}

pub struct LimitTracker<'a, T: 'a + Messenger> {
	messenger: &'a T,
	value: usize,
	max: usize,
}

impl<'a, T> LimitTracker<'a, T>
where
	T: Messenger,
{
	pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {
		LimitTracker {
			messenger,
			value: 0,
			max,
		}
	}

	pub fn set_value(&mut self, value: usize) {
		self.value = value;

		let percentage_of_max = self.value as f64 / self.max as f64;

		if percentage_of_max >= 0.75 && percentage_of_max < 0.9 {
			// 警告: 割当の75%以上を使用していました
			self.messenger
				.send("Warning: You've used up over 75% of your quota1");
		} else if percentage_of_max >= 0.9 && percentage_of_max < 1.0 {
			self.messenger
				.send("Urgent warning: You've used up over 90% of your quota!");
		} else if percentage_of_max >= 1.0 {
			self.messenger.send("Error: Your are over your quota!");
		}
	}
}
#[cfg(test)]
mod tests {
    use super::*;

    struct MockMessenger {
		// 借用チェカーが許可しない
        sent_messages: Vec<String>,     }

    impl MockMessenger {
        fn new() -> MockMessenger {
            MockMessenger { sent_messages: vec![] }
        }
    }

    impl Messenger for MockMessenger {
        fn send(&self, message: &str) {
            self.sent_messages.push(String::from(message));
        }
    }

    #[test]
    fn it_sends_an_over_75_percent_warning_message() {
        let mock_messenger = MockMessenger::new();
        let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);

        limit_tracker.set_value(80);

        assert_eq!(mock_messenger.sent_messages.len(), 1);
    }
}


// output
error[E0596]: cannot borrow immutable field `self.sent_messages` as mutable
(エラー: 不変なフィールド`self.sent_messages`を可変で借用できません)
  --> src/lib.rs:52:13
   |
51 |         fn send(&self, message: &str) {
   |                 ----- use `&mut self` here to make mutable
52 |             self.sent_messages.push(String::from(message));
   |             ^^^^^^^^^^^^^^^^^^ cannot mutably borrow immutable field
```

```rust:コンパルOK
#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;

    struct MockMessenger {
        sent_messages: RefCell<Vec<String>>, // 内部可変
    }

    impl MockMessenger {
        fn new() -> MockMessenger {
            MockMessenger { sent_messages: RefCell::new(vec![]) }
        }
    }

    impl Messenger for MockMessenger {
        fn send(&self, message: &str) {
            self.sent_messages.borrow_mut().push(String::from(message));
        }
    }

    #[test]
    fn it_sends_an_over_75_percent_warning_message() {
        // --snip--

        assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);
    }
}
```

コンパイル時ではなく実行時に借用エラーをキャッチするということは、開発過程の遅い段階でコードのミスを発見し、コードをプロダクションにデプロイするときまで発見しない可能性もあることを意味する
また、コンパイル時ではなく、実行時に借用を追いかける結果として、少し実行時にパフォーマンスを犠牲にする
しかしながら、RefCell<T>を使うことで、不変値のみが許可される文脈で使用しつつ、自身を変更して見かけたメッセージを追跡するモックオブジェクトを書くことが可能になる
代償はあるが、RefCell<T>を使用すれば、普通の参照よりも多くの機能を得ることができる


### Rc<T>とRefCell<T>を組み合わせることで可変なデータに複数の所有者を持たせる

```rust:Rc<RefCell<i32>>で可変化できるListを生成する
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
enum List {
	Cons(Rc<RefCell<i32>>, Rc<List>),
	Nil,
}

use List::{Cons, Nil};

fn main() {
	let value = Rc::new(RefCell::new(5));

	let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));

	let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a));
	let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a));

	*value.borrow_mut() += 10;

	println!("a after = {:?}", a);
	println!("b after = {:?}", b);
	println!("c after = {:?}", c);
}

// output
a after = Cons(RefCell { value: 15 }, Nil)
b after = Cons(RefCell { value: 6 }, Cons(RefCell { value: 15 }, Nil))
c after = Cons(RefCell { value: 10 }, Cons(RefCell { value: 15 }, Nil))
```

借用規則を実行時に精査することでデータ競合を防ぎ、時としてデータ構造でちょっとのスピードを犠牲にこの柔軟性を得るのは価値がある

Cell<T>は、内部や外部へコピーされる点を除き似ている
Mutex<T>は、スレッド感で使用するのが安全な内部可変性を提供する


## 循環参照は、メモリをリークすることもある

Rc<T>とRefCell<T>を使用してメモリリークを許可してしまうこともできる
(要素がお互いに循環して参照してしまう)

```rust
use std::cell::RefCell;
use std::rc::Rc;
use List::{Cons, Nil};

#[derive(Debug)]
enum List {
	Cons(i32, RefCell<Rc<List>>),
	Nil,
}

impl List {
	fn tail(&self) -> Option<&RefCell<Rc<List>>> {
		match *self {
			Cons(_, ref item) => Some(item),
			Nil => None,
		}
	}
}

fn main() {
	let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));

	// aの最初の参照カウント = {}
	println!("a initial rc count = {}", Rc::strong_count(&a));
	// aの次の要素は = {:?}
	println!("a next item = {:?}", a.tail());

	let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));

	// b作成後のaの参照カウント = {}
	println!("a rc count after b creation = {}", Rc::strong_count(&a));
	// bの最初の参照カウント = {}
	println!("b initial rc count = {}", Rc::strong_count(&b));
	// bの次の要素 = {:?}
	println!("b next item = {:?}", b.tail());

	if let Some(link) = a.tail() {
		// a.tailでaのnext要素をbに置き換える
		// Some(RefCell{value:Nil}) を Some(RefCell {value: Cons(5, RefCell {value: Nill })})
		*link.borrow_mut() = Rc::clone(&b);
	}

	// aを変更後のbの参照カウント = {}
	println!("b rc count after changing a = {}", Rc::strong_count(&b));
	// aを変更後のaの参照カウント = {}
	println!("a rc count after changing a = {}", Rc::strong_count(&a));

	// Uncomment the next line to see that we have a cycle;
	// it will overflow the stack
	// 次の行のコメントを外して循環していると確認してください; スタックオーバーフローします
	// println!("a next item = {:?}", a.tail());        // aの次の要素 = {:?}
}
```


### 循環参照を回避する　Rc<T>をWeek<T>に変換する

Rc::cloneを呼び出すとRc<T>インスタンスのstrong_countが増え、strong_countが０になった時にRc<T>インスタンスは片付けられる

Rc::downgradeを呼び出し、Rc<T>への参照を渡すことで、Rc<T>インスタンス内部の値への弱い参照(weak reference)を作ることもできる
Weak<T>型のスマートポインタは、strong_countを1増やす代わりにweak_countが１増える
違いは、Rc<T>が片付けられるのに、weak_countが０である必要はない


#### 強い参照と弱い参照

強い参照は、Rc<T>インスタンスの所有権を共有する方法
弱い参照は、所有権関係を表現しない

ひとたび、関係する値の強い参照カウントが0になれば、弱い参照が関わる循環はなんでも破壊されるので、循環参照にならない
Weak<T>のupgradeメソッドでドロップされているかどうかを判別する Option<Rc<T>> を返す 
ドロップ前ならSome
ドロップ後ならNone


```rust

use std::rc::{Rc, Weak};
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
	// 親のブランチへの弱い参照があるNode
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}

fn main() {
	// 親を参照(弱い参照)している
    let leaf = Rc::new(Node {
        value: 3,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![]),
    });

    // leafの親 = {:?}
	// output: None
    println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());

	// 子を参照(強い参照)している
    let branch = Rc::new(Node {
        value: 5,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![Rc::clone(&leaf)]),
    });

	// downgradeメソッドにより循環参照は断たれる
    *leaf.parent.borrow_mut() = Rc::downgrade(&branch);

    println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
}

// output
leaf parent = None
leaf parent = Some(Node { value: 5, parent: RefCell { value: (Weak) }, children: RefCell { value: [Node { value: 3, parent: RefCell { value: (Weak) }, children: RefCell { value: [] } }] } })
```

無限の出力が欠けているということは、このコードは循環参照していないことを示唆している