Is this "scoped" reduction of lifetime inside of a mutable reference sound?

⚓ Rust    📅 2025-10-27    👤 surdeus    👁️ 4      

surdeus

I have a recursive algorithm with a State<'a> struct containing references.

struct State<'a> {
    x: &'a i32
}

At some points in the recursive algorithm, I would like to store data temporarily in the state struct just for the current recursion and deeper. I can do this by value, but in this case involves cloning data to move it into the state (real value is much more complex than i32).

I'd like to continue to store references, but in this case they are only valid for some shorter lifetime 'scope for the current recursion and deeper, not the 'a lifetime of the full algorithm.

I am exploring a possibility of a pattern which casts the &mut State<'a> to &mut State<'scope> ('scope is strictly shorter than 'a) with a guard which writes the shorter &'scope i32 reference into the struct, and then resets the original value of the field on drop.

Something like

impl State<'_> {
    /// Set a field in `self`, projected by the function `P`, to the value `new_value`.
    ///
    /// The original value of the field will be restored when `ScopedSetState` drops.
    pub fn scoped_set<'scope, P, T>(&'scope mut self, projector: P, new_value: T) -> ScopedSetState<'scope, P, T>
    where
        P: for<'p> Fn(&'p mut State<'scope>) -> &'p mut T,
    {
        // ScopedSetState contains `&'scope mut State<'scope>`, which is cast from `self`.
        // See playground link at bottom of post for full details.
    }
}

As long as great care is taken to not write references into other fields in the state with the shorter 'scope lifetime, I think this can be set up so that it's impossible to produce a dangling reference. (Probably I would do this by having an inner MutableState struct which has pub fields and can only be accessed in the closure passed to scoped_set.)

Miri seems happy, though I wanted to cast this out in case others could find reasons this is unsound anyway?

(Or other concerns I need to protect against?)

Here's a link to the playground.

Thanks for all insight here :folded_hands:

3 posts - 2 participants

Read full topic

🏷️ Rust_feed