Earlier quoted context omitted.
In prehistoric Rust, variance used to be named more explicitly. However, the terminology of covariant and contravariant subtyping of lifetimes is a language theory jargon. This is the right perspective for language design, but programmers using the language don't necessarily use these terms. It's been replaced with a "by example" approach. It's much easier to teach it: just add a fake field that acts if you had this…
Variance is an absolute disaster when it comes to language pedagogy. One of the smartest things Rust ever did was avoiding mentioning it in the surface-level syntax.
Under the hood: Vec
121–130 of 142 posts
Re: Under the hood: Vec<T>
#122But this is wrong, it is no longer the case that `Unique` implies any extra optimizations, since it was since recognized that having these optimizations on a low-level unsafe building block is actually undesirable. Further, the `as_ref` functions mentioned in the article are not used by `Vec`'s internals. They are anyways only marked unsafe because they create references, not because of anything special with `Unique`.
Nowadays, all that `Unique` does is interact with `dropck` in a quirky way, the "exception to the exception." It is quite complicated and I always have to read up on it. It is explained in the Rustonomocon, in the "Click here to see why" section of this chapter: https://doc.rust-lang.org/nomicon/phantom-data.html#an-excep...
Re: Under the hood: Vec<T>
#123Re: Under the hood: Vec<T>
#124Earlier quoted context omitted.
Rust is not the most productive language by any means... it is hardened AF if you avoid unsafe, but productive? I can code much faster in almost any language compared to Rust. It creates mental overhead. For example, to compare it to siblings, Swift and C++ (yes, even C++, but with a bit of knowledge of good practices) lets you produce stuff more easily than Rust. It is just that Rust, compared to C++, comes extra-ha…
Rust is not that bad at prototyping, you need to use the right featureset when writing quick prototype code. Don't use lifetimes, use clone() and Rc/Arc freely to get around borrow-checker issues. Use .unwrap() or .expect("etc.") whenever you're not sure how to pass an error back to the caller. Experiment with the "Any" trait for dynamic typing and downcasts, etc. The final code will still be very high-performance fo…
In fact, most of the time, I would favor styles like this even for not prototyping.
At the end, refactoring is also something natural. I would reserve lifetimes for the very obvious cases wirh controlled propagation or for performance-sensitve spots.
Re: Under the hood: Vec<T>
#125The explanation of `Unique` is a bit botched. `Unique` was originally intended to convey uniqueness in the sense of `noalias`, so that more compiler optimizations are possible similar to what happens around mutable references. This is what the article seems to suggest is going on . But this is wrong, it is no longer the case that `Unique` implies any extra optimizations, since it was since recognized that having thes…
Thank you for your critique and you are right, I struggled with this chapter a lot.
I will read the link to get a better understanding of this type and update the section.
If I may ask, do you have more sources where I can read up on the history and current uses of unique besides the rustonomicon?
Thank you again for your engagement! It is very helpful to get these insights from people with more knowledge.
Re: Under the hood: Vec<T>
#126Re: Under the hood: Vec<T>
#127Earlier quoted context omitted.
that's exactly the footgun. reserve_exact usage needs to be analyzed globally, while `resere` has the extra fuzziness needed to ensure that you can't mess anything up too badly with it.
Calling that a "footgun" feels really overstated. Yes, reserve is the safer default because it gives you slack and preserves amortized growth even if your usage pattern is messy. But "needs global analysis" isn't unique to reserve_exact. Lots of perf knobs do (chunk sizes, buffering, locking granularity etc). The fix to this is to use the tool where its preconditions actually hold, not to avoid the tool. So what I'm…
Dangerous is perhaps overstating it, but the only utility reserve(_exact) has is performance and predictability. If using the API can be worse than doing nothing, I think it warrants being referred to as a footgun.
Re: Under the hood: Vec<T>
#128Earlier quoted context omitted.
Why? It's just a property of type transformation. Assuming Parent - If Generic : it's covariant. - If Generic -> Generic : it's contravariant. - Otherwise: it's invariant. Or at least it's that straightforward in C#. Are there complications in Rust?
Sure, you can keep telling me that and it doesn't stay. I'm completely happy writing Rust, and I am aware it needs variance to work in principle and when I do need that information I know the magic words to type into doc search. It's like how I can hold in my head how classical DH KEX works and I can write a toy version with numbers that are too small - but for the actual KEX we use today, which is Elliptic Curve DH…
Got a Container and want to treat it as a Container? Then you can only write to it: it's ok to put a Cat in a Container that's really a Container.
Reading from it is wrong. If you treat a Container like a Container and read from it, you might get a Dog instead.
The same works in reverse, treating a Container like a Container is ok for read, but not for write.
Re: Under the hood: Vec<T>
#129Earlier quoted context omitted.
Sure, you can keep telling me that and it doesn't stay. I'm completely happy writing Rust, and I am aware it needs variance to work in principle and when I do need that information I know the magic words to type into doc search. It's like how I can hold in my head how classical DH KEX works and I can write a toy version with numbers that are too small - but for the actual KEX we use today, which is Elliptic Curve DH…
One day the rote example finally made sense to me, and I go back to it every time I hear about variance. Got a Container and want to treat it as a Container ? Then you can only write to it: it's ok to put a Cat in a Container that's really a Container . Reading from it is wrong. If you treat a Container like a Container and read from it, you might get a Dog instead. The same works in reverse, treating a Container lik…
Re: Under the hood: Vec<T>
#130> Since a NonNull can never be null, the compiler knows it can use the 0 address to represent the None variant when it sees an Option > I didn't know this about Rust. That's awesome.