anyhow, once I understood that unique_ptr meant nothing like its name but rather something like auto_free_pointer, the pieces sort of fell into place and I experienced almost no memory safety bugs while implementing the compiler, nor has afl-fuzz found any so far 4/5
Conversation
this is all despite my being a thoroughly mediocre C++ programmer. anyhow this story has no real point except that unique_ptr is actually pretty cool and useful, which I had not expected 5/5
11
5
97
Replying to
So good that, in my quite limited understanding of Rust it sounds like everything nontrivial by default is basically a unique_ptr.
2
2
The static enforcement of rules for move semantics and reference aliasing/lifetimes is the interesting part.
Box<T> benefits from those in the same way as any other type. It's quite boring in the Rust world. Any type with a destructor has similar semantics.
1
2
A major difference from C++ in Rust is that assignment, passing and returning values works like C. If the type has a destructor, those have move semantics. A non-trivial copy is done by calling clone explicitly. Rust code uses far more moves and lot more lightweight references.
2
3
I really need to start writing Rust, but it always seems that there's something more pressing to learn
1
2
I don't think you'll really have as much to learn as you think.
As a C++ programmer with a deep familiarity with how memory corruption happens and the semantics you need to avoid it, you largely have an informal and imperfect form of Rust's borrow checker in your head already.
2
4
The main you need to learn is not really syntax, semantics, etc. of the language and libraries. That all comes quite naturally... but rather, you need to learn the idioms needed to work around the static checking. You want to do something and it won't let you. Need to satisfy it.
2
3
It takes experience to avoid resorting to the horror of using Rc<RefCell<T>> which is ugly but at least not as inefficient as std::shared_ptr since it's only atomic if you use Arc to send references across threads and you avoid most reference counts that you'd end up with in C++.
2
4
If you pass an Rc<T> to a function, the variable can't be used again since passing/assignment/returning works like C. APIs usually take &T. If they actually need an owning reference you'd hand over the one you have and only pass it as ref.clone() if you still need it after.
The multi-threaded equivalent to Rc<RefCell<T>> is Arc<RwLock<T>> which essentially explains RefCell<T> to anyone who knows what a RwLock does. It's the single-threaded equivalent: dynamic enforcement of multiple readers or an exclusive writer instead of Rust's static checking.
1
2
More common to use Arc<Mutex<T>> though. Anyway, Rc<RefCell<T>> and the multi-threaded equivalent is the escape hatch when you can't figure out how to do it in a nice way. The dynamic errors for mutable aliasing are the really ugly part and the main reason to avoid RefCell.


