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 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.♥️
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.
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, 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!
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?
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.
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).
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.
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?
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!
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.
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.
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 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.♥️
Noooo ,don't hug he is a nice guy if you hug him he will go ill because of reasons
@@xrafteris he "the gay"?
what is this reply section 💀
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 really really appreciate the 1080p!! Thank you for all your great videos 😃
Super good! Thank you very much for taking the time to produce this video. This is a fantastic approach to show-case "unsafe" in Rust.
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.
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 🤔
Exactly what I thought. Dude checks the existing length for safety, which would already exploded on the previous push if too large
I hit like before I watch the video. I know your videos are informative and full of knowledge. Thanks Ryan!
yeah same lol
Really great video helped me a lot ! Thank you
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!
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?
Missed opportunity to call your vec type LeVec xD
i guess I am kind of randomly asking but do anyone know a good website to watch new tv shows online ?
@Tomas Scott flixportal =)
@Camden Louie Thank you, I signed up and it seems like a nice service :D I really appreciate it!
@Tomas Scott you are welcome xD
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.
As a junior dev, these are great!
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).
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.
Great video! Thanks a lot Ryan!
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?
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!
2 hours about vectors in Rust - so good.
Can you make a video about variance in rust? It's an important topic in unsafe with generics. Might be nice to have a detailed video about it.
Thanks a lot for your time and effort :3
Awesome video, thanks
Here is a like before I even start watching it :) because I know it will be worthwhile!
That is pure gold
That was really nice lesson. Thanks a lot!
Thanks!
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.
Hey I like your videos a lot! May I know what keyboard are you using? Seems like a nice one!
this was awesome
thank you 👍😀
Did you do a video of benchmarking this against the std vector? I'd be quite curious
Thank you for all your videos! Would you mind sharing which shell do you use?
In this video I'm using zsh on WSL.
Awesome video!
Why alloc::alloc(layout) return a null pointer? @Ryan
Thanks
Why are there three "Droppin'" at the end of the video? Shouldn't there be only two as only two items have been pushed into the vector?
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?
The is the rust-analyzer extension marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
Could you please link to the reading of covariance that you referred to?
Here you go! github.com/sunshowers/lifetime-variance-example/
sometimes it's a good thing to reinvent the wheel
Thanks for your teachings.
But what’s the repo link?
It's in the description of the video: github.com/sunshowers/lifetime-variance-example
@@RyanLevicksVideos i meant of your vec implementation
Why if the size of T is 16, its memory address needs to be evenly divisible by 16 ?
compiler nonesense, but proper aligment does help the CPU when shufling data around.
when will u complete gameboy emulator book...??. I'm Having some trouble implementing it..??
At the end you said: "you are totally right".
What did the chat say?
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.
Reference from a raw pointer is unsafe{&*ptr}, it doesn't drop.
The rustnomicon 😱😱😭😦
Article by rain about vi covariant
Here you go! github.com/sunshowers/lifetime-variance-example/
after watching this,:
unsafe{ self.hate_for_rust -= 1; }
Thank you sir