You make a direct comparison between Rust and C++ references, but Rust references are more similar to pointers in many ways. I see people coming from C++ and being confused by this on the forums, so making the direct comparison may be counter-productive.
The compile time guarantees are guaranteed for safe Rust with sound dependencies. Worth pointing out since you have a section on unsafe
. Most of them are UB if they do get compiled.
There are no NULL
references, but there are NULL
pointers.
(More a suggestion:) Although foot-noted, the memory leak seemed out-of-place to me in this list. Perhaps the Mutex
lock too. Both, I guess, fall under RAII.
Here you say
you need a trait object if you want to return different values implementing a trait
But what you actually mean is "if you want to return different types implementing a trait".
The rest of this is suggestion territory, but here you should point out how different the argument position (APIT) and return position (RPIT) uses are.
- APIT is basically a generic parameter on the function, but the type becomes opaque
- You don't need APIT to accept unnameable types in generics, e.g. to be passed a closure
- The caller can choose any type that meets the bounds
- RPIT is opaque, but still a single type (for a given set of parameter inputs)
- I.e. you can't return different types in an
if/else
- The function writer chooses the (single) type that gets returned
And then when you get to returning Box<dyn Trait>
you can compare and contrast with RPIT.
You say
Rust enums are packed tightly,
But they're not really packed, it's more that the variants can share storage because it's a tagged union; only one variant is "active" at a time. (And repr(packed)
is something else entirely.)
Also, the layout (size optimization) is only guaranteed in very specific circumstances. Perhaps mention in general that most Rust data structures have no layout guarantees. You mention niche optimization here too; that almost meets the guaranteed case (as far as I'm aware of it existing), but not quite. So the niche optimization is not guaranteed for the example.
You say
The Iterator trait simply says that you can call next until you get None back
First, there are 74 more other methods so far, so it says a lot more than that.
But also, there's nothing that keeps you from calling next
after you get a None
back. And unless your iterator is fused, nothing that says you'll never get a Some(_)
after you see a None
.
You say
There is always exactly one variable binding which owns a value.
But Rc
and Arc
are often referred to as "shared owneship". Even more nit-picky, a Vec
(say) can be in a single variable binding, but owns multiple values.
I don't have a good suggestion on how to word all this while getting across your original point and not being confusing though.