The mistake I made for my first month of Rust was treating the borrow checker as an adversary to be beaten. You can win those fights. You sprinkle .clone() everywhere, you reach for Rc<RefCell<T>>, you wrap the whole thing in an Arc and tell yourself it is fine. You have not won. You have just moved the argument to runtime, where it is harder to see.
The thing that finally clicked: most of the time the borrow checker is not wrong about the lifetime, it is right about my design. When I have two parts of the code that both want to mutate the same thing at the same time, the compiler refusing to let me is not pedantry. It is the same bug I would have shipped in C and spent a Tuesday afternoon debugging six weeks later, except surfaced now, for free, with a red squiggle.
So I have started losing on purpose. When the checker stops me, instead of fighting, I ask what it is actually telling me about who owns what. Usually the answer is that I had two owners for one piece of state and had not noticed. Splitting that, passing a slice instead of the whole vector, or just restructuring so the data flows one way, makes the error disappear without a single clone. The borrow checker was never the problem. It was the design review I did not know I needed.
I still reach for .clone() when the data is small and the clarity is worth it. That is not defeat, it is a deliberate trade. The defeat is reaching for it without thinking, just to make the red go away.