mozilla/rust — pull request #9429 by blake2-ppc (2013-09-23 17:12:46+00:00)
Title: RFC: Introduce Mut<T>, remove Cell<T>

`Mut` implements an internally mutable slot, using `#[no_freeze]` and `transmute_mut`. It is much like Cell without the nullable part. It implements dynamic borrow checking, which is just an enum counting the current readers and writers.

`Mut` provides methods `.borrow() -> ReadPtr<'a, T>` and `.borrow_mut() -> WritePtr<'a, T>` to obtain a wrapped borrowed pointer. These wrapped pointers have destructors that update the borrow flag in the `Mut` when they go out of scope. Several `ReadPtr` can be alive at the same time.

Example:

let obj = Mut::new(5);
{
let mut m_ptr = obj.borrow_mut();
*m_ptr.get() = 7;
}
do obj.map |t| { println!("value: {}", *t) }

For convenience, and to remove Cell, extra methods are implemented on `Mut>` that make it easy to treat it like an optional value. When replacing Cell's `.take()`, the only overhead of `Mut` at the moment is the destructor function call of `util::NonCopyable` that's inserted.

`Mut` is more generic than `Cell`, and so can replace it better when it is used as an actual mutable slot. This represents very few previous users of Cell in the tree (see commit https://github.com/blake2-ppc/rust/commit/4f8c5b1954aef4e01c40935708757373d9b04b6f )

`Mut` is also used to replace `extra::rc::RcMut` with `Rc>`. This requires a further restriction for cycle prevention (unless I'm mistaken) so that only `T: Send` values are allowed inside `Rc>`. (This is because `Rc>` *is* `Freeze`, while `RcMut` was not.)

### Clarifications and Known issues:

* It doesn't merge. I'll wait for #9359 before rebasing.
* The `BorrowFlag` enum is 16 bytes and is too large. This can be solved inelegantly by simply using an integer.
* `Mut` should be noncopyable because it needs to clear the borrow status when copied.

### Requests for comment:

* Cell is replaced with a more generic type while 90% of users don't need this. Should Cell stay with just the constructor and the single method `.take()`? This represents the use case where closures wish to modify their moved-in upvalues.
* Is it acceptable for a type to have both `impl Mut` and `impl

Mut>` ?
* Should `Mut` allow multiple `ReadPtr` (and thus is has to count them)?