Crust of Rust: Dispatch and Fat Pointers

  Рет қаралды 85,301

Jon Gjengset

Jon Gjengset

Күн бұрын

Пікірлер: 90
@10e999
@10e999 3 жыл бұрын
I'm currently starting the Crust of Rust series from the start. Just here to thank you for your work. The topics are interesting and your examples /explanations well crafted.
@chrisboyce5009
@chrisboyce5009 3 жыл бұрын
These videos are great! For me, the first third is usually "I totally understand what's going on", next third is "I understand some of these words", and make it another 10-15 minutes before starting the video over. The Q&A is really helpful too, since someone in the chat always asks about a specific corner case or exception. It doesn't seem like there is a lot of good intermediate-level material out there, so I'm always excited to see a new video.
@touisbetterthanpi
@touisbetterthanpi 3 жыл бұрын
You don’t even know how helpful this particular episode has been for me. And the detailed chapter markers too have been so nice when I need to refer back. Seriously. Thank you
@SaintlySpirit
@SaintlySpirit 3 жыл бұрын
For those, who prefer visualizations over the long documentation text, visit cheats.rs. For example, the idea of fat pointers can be grasped from the cheats.rs/#references-pointers-ui section. Of course, this site is pretty much of any value if you already know Rust to some extent, but if you do, those little condensed explanations and visuals might be beneficial to the understanding of the whole picture! Thanks for these series, Jon! You should consider doing more visual explanations, whether by hand-drawings (as you rarely do on live coding streams) or by using cheats.rs!
@yotubecreators47
@yotubecreators47 Жыл бұрын
Wow this is cool, thanks a lot
@ihasmax
@ihasmax 2 жыл бұрын
I really appreciate that you touch on very advanced topics while teaching beginner/intermediate ones. I've learned the most from your videos so far and have a deeper understanding of how Rust actually works
@revanthshalon5626
@revanthshalon5626 2 ай бұрын
I came here after reading the book Rust for Rustaceans and this helped me understand a lot better. Thanks a lot Jon!
@Loige
@Loige 3 жыл бұрын
Excellent video as usual! Thanks, Jon. I feel like dynamic dispatch and its constraints make a lot more sense to me now!
@Krzysztow1985
@Krzysztow1985 3 жыл бұрын
Man, I wish I had your skill of explaining things. You're awesome! Of course, the amount of knowledge you have is helping here, but it's a skill on its own.
@KaranKumar-wb5bn
@KaranKumar-wb5bn Жыл бұрын
32:55 this has to be the best explanation. I literally had this doubt and I was about to google how a function would know the size of normal array otherwise. But you explained it so well right after that. Thank you so much for these videos.
@nathanielwoodbury2692
@nathanielwoodbury2692 3 жыл бұрын
Wow. This video was so incredible helping me understand rust deeper. Getting to understand on a more complex level and pushing my knowledge. Thank you so much for this video. I am so grateful for this.
@markay7311
@markay7311 Жыл бұрын
thank you so so much for these streams! I'm very interested in rust internals and I often come to your streams for clarification of complex stuff. really much appreciated
@pcfreak1992
@pcfreak1992 3 жыл бұрын
I love these streams! Please keep them up!
@anssietelaniemi3397
@anssietelaniemi3397 3 жыл бұрын
Really Great content. Opening up the internals explaining how things works under the hood. The missing pieces. And why I am hitting the head in the wall (compiler).
@Codeaholic1
@Codeaholic1 3 жыл бұрын
I love your intro animation.
@omelettttttteeeeeee
@omelettttttteeeeeee 3 жыл бұрын
This is some of the highest quality rust content I’ve seen. Thanks for your work and knowledge-sharing!
@qm3ster
@qm3ster 3 жыл бұрын
I feel like at 1:05:26 you should have also implemented HeiAsRef: pub trait HeiAsRef: Hei + AsRef {} impl HeiAsRef for T {}
@jonhoo
@jonhoo 3 жыл бұрын
Yeah, in practice you'd want that blanket implementation too, but it wasn't really relevant to the discussion around vtables :)
@Zizaco
@Zizaco 3 жыл бұрын
Great video. You gracefully explained what's behind the dyn keyword
@KohuGaly
@KohuGaly 3 жыл бұрын
I wish you have covered the Any trait. It seems like it's super relevant to this topic.
@jonhoo
@jonhoo 3 жыл бұрын
There really isn't much magic to Any. It's just a method that returns a unique type identifier that then allows safe downcasting as I mention at the end :)
@KohuGaly
@KohuGaly 3 жыл бұрын
@@jonhoo I feel like "Can I downcast trait object back to original type?" is a fairly important question when discussing dynamic dispatch. And "Any" trait seems to be the idiomatic way to do it.
@jonhoo
@jonhoo 3 жыл бұрын
@@KohuGaly Ah, so, the answer is that you can only do it *if* your trait object includes the Any trait. You can't use Any to downcast an arbitrary trait object.
@KohuGaly
@KohuGaly 3 жыл бұрын
@@jonhoo So basically, the Any trait is optional... as per "don't pay for what you don't use" principle...
@jonhoo
@jonhoo 3 жыл бұрын
@@KohuGaly Yeah, you can think of it that way!
@CyborusYT
@CyborusYT 3 жыл бұрын
3:04 "Let's get rid of this test, we don't need no test" Famous last words!
@antoniocorbibellot6532
@antoniocorbibellot6532 3 жыл бұрын
Thanks Jon for this enlightening video! Pure Gold. In case someone wants to see in action handcrafted vtables in C-land he/she can have a look at the headers from the Gtk toolkit or even have a look at the C-code output that the vala language compiler produces.
@Knirin
@Knirin 2 жыл бұрын
This video and kzbin.info/www/bejne/Z17CdnV7p5WZrqs which goes over GObject have been very handy for a project of my own.
@TheZethera
@TheZethera 3 жыл бұрын
Thicc pointer
@insomniaccoder806
@insomniaccoder806 2 жыл бұрын
please please.. sir , if u can cover unsafe rust , it would be a great help for the community , but after all iam so glad u prepare this content for us ! tq so much 😃
@VivekYadav-ds8oz
@VivekYadav-ds8oz Жыл бұрын
Isn't a vtable generated for each _type_ , not instance? What is the problem then in inserting a static method inside the vtable? Every other method takes atlest one parameter, but I don't see how not taking a parameter is problematic.
@sodiboo
@sodiboo 2 жыл бұрын
15:33 Technically not entirely true. "Dynamic Libraries" is a broad term, and if you include for example, Windows' Dynamic Link Libraries, those can also contain .NET managed code. Those contain generic functions and types, and it is up to the runtime to "monomorphize" them just in time. But yeah, this is likely not what that question meant, since the context is dynamically linked *native* code
@RiwenX
@RiwenX 2 жыл бұрын
This was super informative, cheers!
@johnnyegel
@johnnyegel 3 жыл бұрын
I just have to comment that this is a brilliant video if you are interested in Rust on a slightly deeper level. Kanonbra! :-D
@-sbin
@-sbin Жыл бұрын
I'm reading your book and decided to look up a video on this concept to understand more... and guess who I find.
@mithradates
@mithradates 3 жыл бұрын
One day implementing that compiler error at 1:06:05 sounds awesome!
@marcorossetti4484
@marcorossetti4484 3 жыл бұрын
Thank you so much Jon! Very helpful!
@willemvanderveen7567
@willemvanderveen7567 3 жыл бұрын
Thank you so much, this is such good content man much appreciated.
@mmghannam
@mmghannam Жыл бұрын
Thanks!
@enbytiousmusic
@enbytiousmusic 2 жыл бұрын
Thank you! Very good Video! Keep it up! Greetings from Germany 👋
@joaodiasconde
@joaodiasconde 3 жыл бұрын
Great content. Like always!
@samighasemi3333
@samighasemi3333 3 жыл бұрын
Thank you for this video
@johanngambolputty5351
@johanngambolputty5351 11 ай бұрын
Missed opportunity for ``` match vial_broken { true => Box::new(DeadCat::new()), false => Box::new(AliveCat::new()) } ``` but Schrodinger hai is good too ;)
@hniksic
@hniksic 3 жыл бұрын
At 1:41:05, should the drop function to accept `v: Box`? In the code as written, `v` is just a reference, so the compiler can't run `Drop::drop()` when it goes out of scope, since its owner might still be using it.
@xrafter
@xrafter 3 жыл бұрын
Same question
@random6434
@random6434 3 жыл бұрын
I disagree with the implementations at 7:34. I think they should still be `s.as_ref().len()` because you should be able to call it with any `T: AsRef`, even if T did not have a `.len()`. The optimizer might then see that for `&str`, `as_ref` does nothing and remove it. Having just `s.len()` makes it seem like there is something magical between `AsRef` and generics, which I don't think there is.
@amaraojiji
@amaraojiji 3 жыл бұрын
Thank you a lot! I love those!
@michaelnajera7958
@michaelnajera7958 3 жыл бұрын
Making me a better swift programmer, thanks. But now you got me curious, how does swift handle dynamic linking of generics?
@jonhoo
@jonhoo 3 жыл бұрын
gankra.github.io/blah/swift-abi/ has all the gory details!
@michaelnajera7958
@michaelnajera7958 3 жыл бұрын
@@jonhoo Thanks!
@ryanleemartin7758
@ryanleemartin7758 2 жыл бұрын
I have my own MIT professor as a Rust mentor for free. Well, don't we live in exciting times!
@kiffeeify
@kiffeeify 3 жыл бұрын
@1:05:40"HeiAsRef". I wonder who that Ref guy is and why he is so hei ;-) Awesome video!
@老夏-u1q
@老夏-u1q 3 жыл бұрын
good tutorial, respect
@HyperFocusMarshmallow
@HyperFocusMarshmallow Жыл бұрын
I’ve been doing a bunch of minor projects in rust and I haven’t even ran into a use case where I’ve needed to use “dyn”. In other languages I’ve used the pattern a lot and maybe it’s just that I’ve worked on a different class of problems than I did in those languages. But I’ve found that I can often get away with using some different pattern in rust. There definitely are use cases where it’s needed, or at least very useful. But where I in some languages would make an interface and put a bunch of generic objects implementing that interface, often I find it more clear to define an enum with variants holding types. That limits how generic the code is. By quite a lot actually. It only allows the possible values I explicitly put in there. But quite often I don’t want to be generic over any object that happens to implement a trait. I just want to be very restrictively generic to exactly 2 or 3 different things that I implement myself. I’ll probably run into it more when I ramp up complexity a bit. That’s why I’m eating the video. But still. We don’t have to be maximally generic for everything we write, just generic enough to make writing the code convenient.
@KohuGaly
@KohuGaly Жыл бұрын
To paraphrase Dijkstra, "purpose of abstraction is not to be vague, but to be precise". A good support for abstraction lets you state precisely what you mean, without forcing you to be more vague or more specific than you want to be. Languages that have interfaces (traits) but no sum-types (enums) force you to over-generalize and therefore force vagueness. They push you to express closed sets of types (enums) as open sets of types (interfaces), even when you actually want a closed set (which is most of the time, actually, as you correctly point out). The main use case for traits and generics is when you want to provide new functionality to types that you have no control over (ie. when you write a library). Or you you have control over those types, but you want to keep it separated to reduce complexity.
@VivekYadav-ds8oz
@VivekYadav-ds8oz Жыл бұрын
Also you said that we can only include "+ " in our variable signature if some_trait is an auto-trait, because auto-traits have no functions. But isn't Any also an auto-trait? It surely has functions, and which have different implementations for each concrete type. Now I'm not really sure how that comes into play.
@jonhoo
@jonhoo Жыл бұрын
No, Any isn't an auto-trait. It has a blanket implementation (impl Any for T), but that's not the same. An auto-trait is one whose impls are generated by the compiler directly based on the structure of the type, and they never have any methods, which is not the case for Any.
@juchemz
@juchemz Жыл бұрын
1:29:25 I still don't understand why it's not possible to monomorphize the vtables. We compile the standard library at the same time as the rest of our code, so it should be possible to know the size of the vtable for a type+trait after monomorphization, even if it is large, and use that everywhere in our program. My vtables will be differently sized than yours, but that's just a different flavor of the same issue preventing us from having dynamic libraries.
@juchemz
@juchemz Жыл бұрын
Listening to your explanation again, I think my mistake is that we don't actually compile the standard library at the same time, we compile one crate at a time and just have access to the source for other crates. So for a normal generic function, if we introduce a use that std doesn't have, it would get compiled along with our crate, not std
@hmmmyessssssss7270
@hmmmyessssssss7270 Жыл бұрын
44:30 "you can keep using box after the stack frame of the caller has gone away", how is this situation possible? Won't the caller return only after this function has returned?
@timanderson5717
@timanderson5717 3 жыл бұрын
can't the generic method thing be solved by more dynamic dispatch? I.e. The vtable for Extend has extend?
@alliu6757
@alliu6757 3 жыл бұрын
Thank you for your videos. Could you do a video about epoll and io_uring for file I/O?
@TomasSandven
@TomasSandven 2 жыл бұрын
Holy shit you’re Norwegian!? Your English is amazing. Hilsen fra Molde :)
@blablaqwertyful
@blablaqwertyful 2 жыл бұрын
It's tempting to say that type erasure causes all trait-related problems. Is it required that much to generate an efficient code? Why can't we preserve types?
@keent
@keent Жыл бұрын
does anyone know what theme is he using? looks pretty neat edit: looks like gruvbox or something
@32zim32
@32zim32 3 жыл бұрын
s::weird is no possible because s doesn not name a type As you said type erasure occurs and the only thing you have is pointer to data and pointer to methods table Compiler does not need to know s type to call needed method I think the main reason is because in machine code level calling method through indirection is compiled into some stuff, which requires pointer to data to be available at this point. That's the main goal of dynamic dispatch and polymorphism. Method without self parameter can only be invoked through concrete type, which make no sense to include it in vtable which is needed only for magic like calling method without knowing type of object this method is called on
@elgusanito6991
@elgusanito6991 3 жыл бұрын
Who is the guy who disliked the video?? Let's locate him and sacrifice his soul for the sake of nightly rust.
@xrafter
@xrafter 3 жыл бұрын
@@JohnWalton_NET .Its going out of hand , now there are six of them
@araz911
@araz911 21 күн бұрын
sorry, but I accidentally read guy asgay 😂 but anyways, nice vide
@araz911
@araz911 21 күн бұрын
o
@tdwebste
@tdwebste 3 жыл бұрын
Document describing your vim setup. Please :)
@ivanzvonimirhorvat9744
@ivanzvonimirhorvat9744 3 жыл бұрын
IMHO It would be nice if you showed (traits) fat pointer representation with the debugger
@mariuskriegerowski8378
@mariuskriegerowski8378 10 ай бұрын
This is clearly an outlier: Usually I watch tutorials on youtube at playback speed = 1.5 (+- 0.25) because of relatively low information density. But crust of rust is often < 1.0. Thick (high quality) material to digest.
@jawad9757
@jawad9757 2 жыл бұрын
What font do you use?
@OkamioftheRinnegan
@OkamioftheRinnegan 3 жыл бұрын
Why does an unsized type have to be the last field in a struct if the compiler is allowed to reorder fields anyway?
@KohuGaly
@KohuGaly 3 жыл бұрын
Because fields of struct are accessed as pointer offsets. For sized types, compiler may choose to reorder them, but compiler still knows where each field is located relative to the head of the struct. That does not work for unsized types. Because compiler can't know its size, then it can't access fields after it as offsets, because it can't figure out how big the offset should be. The only place where you (and the compiler) can put it is at the end of the struct.
@antonioquintero-felizzola5334
@antonioquintero-felizzola5334 3 жыл бұрын
Hey Joh, what's the font you use in your terminal?
@parthikpatel6108
@parthikpatel6108 3 жыл бұрын
How do you get your navigation bar/tabs on the bottom? Is that a firefox extension?
@softwarelivre2389
@softwarelivre2389 3 жыл бұрын
25:50 so we want something similar to Duck Typing in Typescript? Interesting
@jeffg4686
@jeffg4686 3 жыл бұрын
Where is Norwegia?
@jeffg4686
@jeffg4686 2 жыл бұрын
@Leon Tepe - yeah, i know. I always just think it sounds funny
@TheKaratekidd32v
@TheKaratekidd32v 3 жыл бұрын
Thanks for adding timestamps to these videos! It makes it easy to watch a couple 'chunks', and come back to the video later.
@thepuzzlemaker2159
@thepuzzlemaker2159 3 жыл бұрын
Thanks!
@qm3ster
@qm3ster 3 жыл бұрын
in `struct Foo {f: bool, t: [u8], x: bool}` why can't the offset of `x` be determined by `len-sizeof x`? (such a struct combined with a #[repr] would be good for some zero-copy network encoding stuff)
@jonhoo
@jonhoo 3 жыл бұрын
In general the compiler expects field offset to be constant. You could imagine extending it to be dynamic, but that's a big language feature in and of itself.
@AllTheFishAreDead
@AllTheFishAreDead 3 жыл бұрын
Hey, great video - I have a noobie qn. Early on you discuss how in the trait object case you need the function argument to be sized so you can make a collection of them where each thing, the pointer type, is of the same size. However later on you say we can have a trait not add a static method to the vtable by requiring Self be sized, saying that the trait, dyn Hei, has no size. But didn't we pass a reference so that it was sized? Thanks!
@xrafter
@xrafter 3 жыл бұрын
Reference is sized not the object
@kushagragupta7051
@kushagragupta7051 3 жыл бұрын
at around 1:05:52 when you talked about the multiple trait vtable, you said to create a new trait that requires the needed traits and use that. It would give a bigger vtable but it would still be 1 pointer right? And it would lead to code duplication as either the compiler would copy the trait implementations to another location or it would copy the function labels and call the original implementation methods. Wouldn't that be inefficient? Is there a way to say that I do want to generate a 3 pointer wide or even wider (based on number of traits) argument? with each pointer pointing to one traits vtable?
@ekrem_dincel
@ekrem_dincel 3 жыл бұрын
You can already do what you describe yourself by using custom vtables but trait objects don't work like that. And compiler only copies vtables, which usually has the size of (pointer_size * method_count). Basically it is a very very little overhead.
Crust of Rust: Functions, Closures, and Their Traits
1:06:40
Jon Gjengset
Рет қаралды 89 М.
Crust of Rust: Send, Sync, and their implementors
1:07:04
Jon Gjengset
Рет қаралды 44 М.
HAH Chaos in the Bathroom 🚽✨ Smart Tools for the Throne 😜
00:49
123 GO! Kevin
Рет қаралды 14 МЛН
Every parent is like this ❤️💚💚💜💙
00:10
Like Asiya
Рет қаралды 8 МЛН
Rust Powered Polymorphism ⚡️ With Traits
9:55
Code to the Moon
Рет қаралды 99 М.
Crust of Rust: Atomics and Memory Ordering
2:39:20
Jon Gjengset
Рет қаралды 84 М.
Rust stole C++'s best features
8:47
Let's Get Rusty
Рет қаралды 59 М.
Crust of Rust: Smart Pointers and Interior Mutability
2:03:04
Jon Gjengset
Рет қаралды 125 М.
Rust Functions Are Weird (But Be Glad)
19:52
Logan Smith
Рет қаралды 136 М.
All Rust string types explained
22:13
Let's Get Rusty
Рет қаралды 172 М.
Rust + Next-Gen SQL Databases = 😍
13:53
Code to the Moon
Рет қаралды 23 М.
Two Ways To Do Dynamic Dispatch
19:54
Logan Smith
Рет қаралды 75 М.
Crust of Rust: Iterators
1:26:27
Jon Gjengset
Рет қаралды 99 М.
Crust of Rust: async/await
2:34:01
Jon Gjengset
Рет қаралды 193 М.