Re:Rust for C++ programmers – part 5: borrowed references
by pcwalton on Tuesday May 06, 2014 @01:20PM
(#7705816)
You can use privacy for (1); admittedly it's a little hokey, but I feel it's not worth the added complexity to add field-level immutability directly into the language since you can use other language features to effectively achieve it. `std::cell::Cell` and `std::cell::RefCell` give you (2).
Re:Rust for C++ programmers – part 5: borrowed references
by azth on Tuesday May 06, 2014 @05:03PM
(#7707074)
> `std::cell::Cell` and `std::cell::RefCell` give you (2).
What advantages does (2) provide? Isn't it a potential source of errors?
Re:Rust for C++ programmers – part 5: borrowed references
by pcwalton on Tuesday May 06, 2014 @06:33PM
(#7707544)
It is, but sometimes you have to do it for practicality. Usually this comes up when people use `Rc<T>`, as that only supports immutable types (so any mutability you want needs to be in the form of `Cell`/`RefCell`).
Re:Rust for C++ programmers – part 5: borrowed references
by azth on Tuesday May 06, 2014 @07:20PM
(#7707755)
Would it be better to combine both types (e.g. a MutRc<T> type), and get rid of Cell/RefCell?
Re:Rust for C++ programmers – part 5: borrowed references
by pcwalton on Tuesday May 06, 2014 @07:49PM
(#7707854)
I don't think so, because then you'd get an overconservative iterator invalidation checker. For example:
struct Foo {
a: Vec<int>,
b: Vec<int>,
}
let foo = Rc::new(RefCell::new(Foo::new(...)));
for x in foo.borrow_mut().a.mut_iter() {
for y in foo.borrow_mut().b.mut_iter() {
// ^^^ FAILURE: a is already borrowed mutably
}
}
The failure happens because the RefCell is checking to make sure there are no two `&mut` references at the same time to `Foo`, to prevent iterator invalidation. But this is silly, because it only needs to prevent access to `a` while you're iterating over it, not both `a` and `b`. Changing the definition of `Foo` to this fixes the problem: struct Foo {
a: RefCell<Vec<int>>,
b: RefCell<Vec<int>>,
}
Re:Rust for C++ programmers – part 5: borrowed references
by azth on Tuesday May 06, 2014 @09:57PM
(#7708220)
Makes sense. Though Cells would really stand out in the code as a potential for race conditions (unless you get a run time failure?). Thanks for the insight.
Re:Rust for C++ programmers – part 5: borrowed references
by pcwalton on Wednesday May 07, 2014 @12:53AM
(#7708657)
There is a special bound--Share--that is required on thread-safe data structures and forbids Cell/RefCell. The thread-safe equivalents of Cell and RefCell are Atomic and Mutex, respectively.
Re:Rust for C++ programmers – part 5: borrowed references
by steveklabnik on Tuesday May 06, 2014 @01:15PM
(#7705777)
Ahh, thank you. And yes, that's what I'd argue.
1. The pointer is mutable, but its contents are immutable.
2. The pointer is immutable, but its contents are mutable.
3. The pointer is immutable and the contents are immutable.
4. The pointer is mutable and its contents are mutable.
Right now for owned pointers Rust gives us (3) and (4), but no obvious way to achieve (1) and (2). Although you might argue that the borrowing semantics give us these powers, just not directly with owned pointers - which we shouldn't be using directly if we're asking for that control, we should be lending them out in a well-controlled manner.