Lifetime issues with mutable borrow in a loop

⚓ Rust    📅 2026-01-01    👤 surdeus    👁️ 11      

surdeus

Warning

This post was published 71 days ago. The information described in this article may have changed.

I'm working on refactoring code from owned data to borrowed data, and I've hit a lifetime issue with mutable borrows in a loop. The working version (with owned data) compiles fine, but the borrowed version fails.

The Problem:
I have a trait method that takes a mutable scratch space and returns an iterator. When the iterator borrows from the scratch space, I can't call this method multiple times in a loop:

fn ref_records<'point, 'scratch, ScratchT: ScratchSpaceRegistry>(
    &'point self,
    scratch: &'scratch mut ScratchT,
) -> RefIterResult<'point>  // Returns Result<Box<dyn Iterator<Item = RefRecord<'point>> + Send + 'point>, String>
where
    'scratch: 'point;

When I try to call this in a loop:

for point in data {
    let records = point.ref_records(scratch)?;
    Self::handle_point_ref(point, records, &mut inserter).await?;
}

Compiler Error:

cannot borrow `*scratch` as mutable more than once at a time
`*scratch` was mutably borrowed here in the previous iteration of the loop

The Working Version (for comparison):
This version works fine because the iterator doesn't borrow from scratch:

fn records<'point, 'scratch, ScratchT: ScratchSpaceRegistry>(
    &'point mut self,
    scratch: &'scratch mut ScratchT,
) -> OwnedIterResult  // Returns Result<Box<dyn Iterator<Item = Record> + Send>, String>
where
    'scratch: 'point;

The returned iterator contains owned Record values with no lifetime parameters, so the borrow of scratch ends immediately.

My Question:

Is there a way to express that the mutable borrow of scratch should only last as long as needed for deserialization, even though the returned iterator lives for 'point? Or is this a fundamental limitation where I need to restructure my API? If I need API restructuring, what would be a good way to handle this ?

The full code is available here: Rust Playground

I've tried various lifetime annotations but can't find a way to tell the compiler that scratch is only borrowed temporarily during iterator construction, not for the iterator's entire lifetime.

7 posts - 3 participants

Read full topic

🏷️ Rust_feed