I love you for taking your time and effort for making these great videos possible. I know you must have busy schedules, even though you are doing this. This is totally amazing for me. I am just craving to give you a hug for this 😭 Thank you so much.♥️
Love the way you make these tutorials :). Instead of teaching individual concept, we learn more when you build stuff like these. Hoping to see you build more complex projects in coming sessions.
I am new to rust (have been learning for about 2 weeks or so), and haven't slept in over 24 hours now, and this still makes perfect sense. I think you have a talent for explanation and not going too slow or fast. Keep up the good work!
I didn't know that using *ptr = val is unsound for uninitialized memory but you're right, the documentation says it will drop the previous value in there.
Thank you, this is incredibly useful for learning how to implement data structures with unsafe components and also taught me a lot about how to approach writing unsafe rust. I’ve found that writing some data structures in safe rust can be extremely tedious and inefficient!
There's indeed a very good reason to write your own vector implementation. The vector of the standard library is optimized for general purpose use not for performance nor memory efficiency. When it comes to high memory restrictions or perf ciritical code, where you need for example custom allocation strategies, different amortized memory growth or different destruction behaviour, the standard vector is pretty much useless. No wonder C++'s boost has many different vector-like implementations for different use cases.
It looks like you press "escape" "up" "down" compulsively. ... I do, too...why do we do this? I use kinesis advantage and vim. What kind of keyboard do you use? Thank you for the walkthrough!
Seems that at 1:07:40 the `self.len.checked_mul(...)` must be `(self.len+1).checked_mul(...)` as this way we're checking not only starting offset of a pointer, but rather resulting offset of the pointer and making sure it doesn't wrap around when the actual operaiton of `ptr.as_ptr().add(self.len)...` is finished 🤔
Thank you for your great videos. I think there is an error in the push method when you check the rounded value : you should add "align - size % align" instead of "align % size".
To see why this is the case, notice that size = k*align + (size % align) for some integer k. Then size + (align - size % align) = (k+1) * align, aka the nearest multiple of align rounding up from size. In the example of size = 10 and align = 4 it was just bad luck that align - size % align = align % size = 2, so you had the right outcome by accident.
At ~ 1:10 why use the from_size_align_unchecked() and manually do the prerequisite safety checks, instead of using from_size_align() which does those checks for you? Am I missing something?
Hey, a philosophical programming languages question, especiaally with NonNull and its dangling() constructor: isn't a dangling pointer much more dangerous than a null pointer? At least with a null pointer you get a crash directly which ist a very localized and easily debuggable problem, while with a dangling pointer you have silent failure with possible data corruption in the worst case.
A bit late a reply, but the reason Vec does this is is for a neat trick: because the pointer can never be null (even if it's not valid to access), this gives the type a "niche" that the compiler can squeeze a an extra literal bit of information out of, which means that you can store an Option without any more space than a Vec.
Given that a dangling pointer can be constructed without the "unsafe" block, I'm pretty sure that the compiler will ensure that you won't be able to dereference the dangling pointer (in safe Rust). In contrast, in C and C++, because there is no such mechanism of memory safety check baked into the language, there is NEVER a good reason to assign a pointer as NULL. (In C++, it can be replaced by nullptr).
Great video! Got to learn a lot about how to deal with various safety checks before writing unsafe code. Just had a doubt.. is it possible to take reference outside the unsafe block in the get method. (I think I should rather ask if it's possible to return the dereferenced value outside the unsafe block, which shouldn't be possible according to me but please correct me if I'm wrong) Also, would love to go through more content covering varied use cases around unsafe code. Really appreciate your efforts for taking this approach of teaching advanced concepts.
0:38:27 I think since an unsized type may have only one value (memory is the same), a flag can be kept to true and store the single value of the unsized type. then based on length & capacity we just return a copy of that same value when pop is called. Would that work? do you any issue with that?
For testing, he actually created another instance of `Dropped` to put into the assert to compare it to what was in the MyVec. So there's two `Dropped` in the MyVec, and a third one he created for the assert that he's comparing it to. That's why he rearranged to code in the very end, moving the creation (and scope) of this third instance outside of the assert, to show that this is what was created and then dropped.
Anyone know what VS Code plugin he's using that gives the type inference lens like that? E.g. that it shows him the inferred type is Vec. Is that part of the standard Rust VS Code plugin and I missed it?
They simply pointed out that there was another instance of `Dropped` which I was creating in the test which was the reason we saw a third printing of "droppin'". I originally thought this was a double drop of the same instance (which would make our implementation wrong), but it wasn't. The code was totally fine. At the end I simply rearrange the test to demonstrate that the drops happen when we expect them to happen (at the end of the test function).
He had two `Dropped` in the MyVec, but he actually created a third one to compare in the assert, and that's why there were three droppin's. So it wasn't a bug, just the test code.