Cell

Cell<T>は型はミュータブルでもイミュータブルでもT値を変更可能な形で使うことができます。シングルスレッドでのみ使えます。

Cellで値の取得と更新はそれぞれ::get::setを使います。以下ではcell_i32はイミュータブルでの定義ですが、それらメソッドを使って値の更新ができています。

use std::cell::Cell;

let cell_i32: Cell<i32> = Cell::new(33);
let ref_cell_i32 = &cell_i32;

cell_i32.set(cell_i32.get() + 1);
ref_cell_i32.set(ref_cell_i32.get() + 1);
{
  let ref_cell_i32_in_scope = &cell_i32;
  ref_cell_i32_in_scope.set(ref_cell_i32_in_scope.get() + 1);
}

assert_eq!(cell_i32.get(), 36);

しかし、ここでCell<String>で同じようなコードを書いてみます。

use std::cell::Cell;

let cell_string: Cell<String> = Cell::new("foo".into());

assert_eq!(cell_string.get(), "foo".to_string());

これは動きません。エラー文を見ると「::getは有るけど、Tstd::marker::Copy実装してないよ」のように書いてあります。

the method get exists but the following trait bounds were not satisfied: std::string::String : std::marker::Copy

このことからCell<T>Tstd::marker::Copyを実装済の型を渡さなければ意味がありません。

もしstd::marker::Copyな値を同じように扱いたいならRefCell<T>があります。