Rust, at it’s core, is a programming language of restrictions. These restrictions exist for good reason. Upon encountering a restriction, however, it’s common to attempt to find the easiest work-around, rather than understanding the why the restriction exists in the first place.
Operating from the perspective of needless restrictions, Rust’s limitations become annoyances to memorize: don’t make that mutable here, box that async future there, make sure that trait is sized, etc.. If you take a step back, however, and look at questions surrounding the core principles of Rust—e.g. ‘what would it take to implement borrow checking?’ or ‘why does Rust’s async implementation require boxing so often?’—you’ll soon find that a lot of these restrictions are a natural consequences of the design of the language and its compiler.