Interesting question. I've allowed myself to distance a bit from Rust'ing around for the last several months, as slightly more higher-level projects, such as an app I'm currently building, in Flutter, which a Dart framework, have sucked all of my attention, but I still love Rust. The safety, the speed of nearly raw-metal execution, along with higher level constructs baked directly into the language - all represent an insanely powerful combination.
With that said, as of today it still isn't a language to be used everywhere - I certainly wouldn't use to build any kind of app for a mobile device, that's for sure. And as much as the community might like to tell everyone to "just build it in Rust" would like to see the rate of adoption of their favorite tool grow over time, there are a lot of other languages that are just good enough for their particular use case.
If you need to rapidly test a web idea you have, it's much easier to go for a Node backend + some JS framework than try to compile all of your favorite Rust constructs into a WASM binary to link to in your web page, before serving it with Actix Web - the first compilation process on its own will take you much longer than initialization of a simple "hello app" in React or Angular.
If you're looking to build games - there is Unity. Tons of community packages available, tons of tutorials - you'll be starting on a solid foundation of people that have "been there, done that", and you won't have to concern yourself with all the nooks and crannies of semi-esoteric lifetime-annotated dynamically generated functions, bound by traits you never imagined would be important for the functions that you're putting together.
Still, going back to your question - about becoming a Rust'inja (can we shorten Rust Ninja to that?) and really mastering what the language has to offer. This just hit me earlier. If you're coming from any other language, other than C/C++, you're most likely to think about any "data" you work with as an "object". It's a "thing" that has some "properties" and that can "do" something with its "methods". Rust takes this notion of yours, looks at it, looks at you, smirks, slaps you across the face with it and throws it out of your freaking window.
Rust doesn't think in "objects". It doesn't care about them, their properties or their methods.
Rust thinks in contracts and expectations. Some of which are defined by you, and most of which were defined before you, by a bunch of a very bright folks who have spent 10s of years trying to create solid software which wouldn't crash when they'd put in front of their users, failing over and over, before deciding there is a better way.
A way that involves restricting you as much as possible from shooting yourself in the foot, while providing you with the same power you have when coding in C++, including managing your memory explicitly, allocating and deallocating it as needed - which is where most of the problems that new people have stem from. With great power comes great responsibility - and Rust tells you exactly what those responsibilities are. Whether you like it or not.
All the things you've listed in your post are the examples of these contracts and expectations. Subtypes, variance, traits, lifetimes, implementations, proper iterations - all represent the different expectations that Rust compiler expects you to meet before it ever thinks about compiling and running your code.
Some of them are straightforward. You have a Struct with typed fields, which you pass as a reference to a function for it to print some data you have there. Simple enough. Now try to think about how you'd implement an asynchronous stream of data, from scratch - starting from a simple:
fn main() {
println!("Hello World!");
}
Would you even know where to start? Some people do - and they've created a ton of libraries for you to use. They followed Rust's contracts perfectly (otherwise it wouldn't compile). And now you're expected to follow those contracts to the letter yourself. Why? Because otherwise your program will crash and burn, and you will crash and burn with it - and the whole world will crash and burn around you, and you will be held responsible for it, even though you'll be dead by that point. Rust puts restraints on you to make sure that doesn't happen - as long as you stay out of the Unsafe world. And given how insanely hard it is to wrap your head around the usual expectations Rust places on you - it's quite expected that by the time you get into the prohibited land you'll be more than able to survive there on your own.
In terms of the training path, struggles and projects. The best training path is the one that is meaningful. Decide what you're going to focus on. If it's game design, start with Unity - by the time you master it, you're most likely going to be able to implement the basics in any language, including Rust. Web development? Node JS. Once you've figured out (well, really well) the lower-level details, you'll be ready to tackle Rust's "zero compromise" approach to server-side part of the programming world.
Systems programming or embedded devices, on the other hand? Well then, Rust can be your best teacher here indeed. But the choice remains up to you - decide what you'll be working on, start tackling that projects and master the concepts that you need to master on your way there. You'll soon understand what those "?Sized
" - things are and why they need to be specified at times. It'll become obvious where should those "Sync + Send
" go and why the lifetimes can help you out.
Struggles are normal. Meaningless struggles that you don't need - aren't. Pick your projects according to what you want to accomplish in the end - and gradually move there. Unless you have a ton of free time at hand and the best way you can think of spending it is by mastering the Rust-speak. In that case, just pick a project at random and start squeezing all of the things you've listed in your post, along with all the Nomicon info, along with random pieces of code from Tokio, along with random low-level libraries you find on crates.io or lib.rs - as long as they seem interesting.
Be ready to bang your head against the table for many days, weeks, perhaps even in a month in a row until you finally reach enlightenment. Trial and error is an essential learning tool - no one can learn the material you're learning for you, and the best way to master anything is by practicing putting it to a good use. And should you get stuck - just ask around here. As long as the question is not too long, pertinent to one particular concept and respectful - people here are more than willing to help.
P.S. Just don't expect any emojis in the answers. Rust masters are stern, concise and direct. Unless there's an opportunity to kindly tell someone that they're a noob - no one will miss that chance.
P.P.S. That was a joke - although I do believe that being a bit less strict with punctuation and using at least some smiling faces or emojis will only benefit Rust's adoption, especially among beginners