So, I'm new to Rust and I'm facing this problem for weeks, since the beginning I guess. I've always thought a good way to learn a language is by making a simple game with it, so here I am. I've tried both with SDL2 and with SFML bindings, and with both I end up having the same problem: When you create a sprite, you pass it a texture, and the texture lifetime cannot be smaller than the sprite (otherwise you'd have a sprite displaying garbage).
So, at some point in my code, I end up creating an instance of an struct that requires an explicit lifetime. And in order to make it work, this explicit lifetime ends up being used all over the place, until it reaches main, where you get the error that you can only mutably borrow once.
By accepting a lifetime-bounded reference, the library is requiring you to structure your code so that the compiler can prove that the Sprite is destroyed before the Texture. In the simplest case, this means you can have all your textures owned by main, which provides references into the game loop function. When the game is over, control returns to main() which then cleans up the textures.
Alternatively, you can create and destroy the Sprite structures every frame. This adds some complexity to the main game loop, but lets you use a more flexible strategy for managing the texture data.
The complete hack of a solution is to use Box::leak() to never clean up the textures, and just rely on the OS doing that for you at program exit. That’ll give you ’static references, so you can dispense with the lifetimes altogether.
Not a solution to your issue, but just some thoughts:
I think to a degree, these issues are just a consequence of trying to make those existing C APIs fit in with Rust. The lifetimes are awkward because the underlying code was not written with this kind of memory management in mind, but removing them would make the code completely unsafe.
Most Rust-based game frameworks (that I've seen, at least) use reference counting instead of explicit lifetimes to manage textures and other assets that need to be freed. This makes using them feel a lot more like you might expect coming from other languages (i.e. cheap to clone, cleaned up automatically when no longer used).
If your goal is 'learn the language/learn to make a game' rather than specifically 'learn to use SFML/SDL in Rust', I would recommend trying one of those frameworks instead - there's a good rundown here with some code examples (disclaimer: I wrote Tetra, which is mentioned in the list).
Unless you're doing something quite advanced, I don't think there's a ton of situations where you'll have to deal with long-lived structs with lifetime annotations in Rust (for exactly the reasons you've stated already - they can quite awkward to work with).
It's much more common to use them when you're making a short-lived 'view' into another piece of data - e.g. if you were writing a parser and you wanted a Token struct/enum to hold a reference into the input, plus some extra metadata.
In other words, hopefully this doesn't colour your first impressions of Rust too much