Comment by ozgrakkurt
6 hours ago
returning "impl Trait". async/await unpin/pin/waker. catch_unwind. procedural macros. "auto impl trait for type that implements other trait".
I understand some of these kinds of features are because Rust is Rust but it still feels useless to learn.
I'm not following rust development since about 2 years so don't know what the newest things are.
RPIT (Return Position impl Trait) is Rust's spelling of existential types. That is, the compiler knows what we return (it has certain properties) but we didn't name it (we won't tell you what exactly it is), this can be for two reasons:
1. We didn't want to give the thing we're returning a name, it does have one, but we want that to be an implementation detail. In comparison the Rust stdlib's iterator functions all return specific named Iterators, e.g. the split method on strings returns a type actually named Split, with a remainder() function so you can stop and just get "everything else" from that function. That's an exhausting maintenance burden, if your library has some internal data structures whose values aren't really important or are unstable this allows you to duck out of all the extra documentation work, just say "It's an Iterator" with RPIT.
2. We literally cannot name this type, there's no agreed spelling for it. For example if you return a lambda its type does not have a name (in Rust or in C++) but this is a perfectly reasonable thing to want to do, just impossible without RPIT.
Blanket trait implementations ("auto impl trait for type that implements other trait") are an important convenience for conversions. If somebody wrote a From implementation then you get the analogous Into, TryFrom and even TryInto all provided because of this feature. You could write them, but it'd be tedious and error prone, so the machine does it for you.
Like you said it is possible to not use this feature and it arguably creates better code.
It is the right tradeoff to write those structs for libraries that absolutely have to avoid dynamic dispatch. In other cases it is better to give a trait object.
A lambda is essentially a struct with a method so it is the same.
I understand about auto trait impl and agree but it is still annoying to me
Returning impl trait is useful when you can't name the type you're trying to return (e.g. a closure), types which are annoyingly long (e.g. a long iterator chain), and avoids the heap overhead of returning a `Box<dyn Trait>`.
Async/await is just fundamental to making efficient programs, I'm not sure what to mention here. Reading a file from disk, waiting for network I/O, etc are all catastrophically slow in CPU time and having a mechanism to keep a thread doing useful other work is important.
Actively writing code for the others you mentioned generally isn't required in the average program (e.g. you don't need to create your own proc macros, but it can help cut down boilerplate). To be fair though, I'm not sure how someone would know that if they weren't already used to the features. I imagine it must be what I feel like when I see probably average modern C++ and go "wtf is going on here"
Impl trait is just an enabler to create bad code that explodes compile times imo. I didn’t ever see a piece of code that really needs it.
I exclusively wrote rust for many years, so I do understand most of the features fair deeply. But I don’t think it is worth it in hindsight.