Lifetime issues with an internally mutable struct


#1

I’m having some lifetime troubles while trying to implement a crude state machine that outputs animation frames. Here’s a playground with a simplified case, but the gist is that a Pose is internally mutable and iterates through its Frames with a cursor and a next method. A StateMachine wraps a Pose and is responsible for swapping out one pose for another, when it determines it’s time to transition.

https://play.rust-lang.org/?gist=58c9e29bac6583862d42564b43fdfdf0&version=stable

I think the root of the problem is that the lifetimes of Next and Pose tie them together even though they aren’t really dependent on each other, so the compiler thinks that calling self.current.next() (a Pose method, returning a Next) is the same as borrowing self.current.

There’s also the likely possibility that I’m just Doing State Machines Wrong and a different approach wouldn’t require jumping through these hoops.

I’ve been juggling a lot of lifetimes to try to make this work, but the only time it will compile is when the structs’ internal slice references are 'static, so the struct’s lifetime annotation can be left off. However I feel like I need to leave them generic because these structs will need to be used both in an embedded environment (when all of the dependent data does in fact have 'static lifetimes, written into the binary with a procedural macro) and also when they’re created at runtime in those procedural macros and in a non-embedded “preview” app.

If anyone could help me untangle this, I’d appreciate it.


#2

You just have to make a small tweak: in Pose::next, change the return type to Next<'a>. Lifetime elision rules otherwise make the lifetime there the same as the elided one on &mut self and that propagates the borrow of self unnecessarily.


#3

Aaaah, you’re right, thanks so much


#4

The above is the right way to fix that code, but it’s also worth mentioning that your code works as-is with NLL (non lexical lifetimes) enabled: https://play.rust-lang.org/?gist=487e957623d6f8628a4aef0f057b5e5f&version=nightly