Cell<T>は型はミュータブルでもイミュータブルでもT値を変更可能な形で使うことができます。シングルスレッドでのみ使えます。
Cellで値の取得と更新はそれぞれ::getと::setを使います。以下ではcell_i32はイミュータブルでの定義ですが、それらメソッドを使って値の更新ができています。
use std::cell::Cell;
let cell_i32: Cell = 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 = Cell::new("foo".into());
assert_eq!(cell_string.get(), "foo".to_string()); これは動きません。エラー文を見ると「::getは有るけど、Tはstd::marker::Copy実装してないよ」のように書いてあります。
the method
getexists but the following trait bounds were not satisfied:std::string::String : std::marker::Copy
このことからCell<T>のTはstd::marker::Copyを実装済の型を渡さなければ意味がありません。
もしstd::marker::Copyな値を同じように扱いたいならRefCell<T>があります。