Lifetime issues with mutable borrows to mutable slices

⚓ Rust    📅 2025-07-08    👤 surdeus    👁️ 4      

surdeus

I have a mutable reference to a slice, I want to write a function which puts data into a slice and then advances a mutable reference by the amount of data written.

This was my first version which didn't compile.

fn extend<'a: 'p, 'p>(out_buf: &'p mut &'a mut [u8], data: impl AsRef<[u8]>) {
    let bytes = data.as_ref();
    let len = bytes.len();
    {
        let buf: &'a mut [u8] = &mut out_buf[0..len];
        buf.copy_from_slice(bytes);
    }

    *out_buf = &mut out_buf[len..];
}

At first I tried to change the lifetime bounds to 'p: 'a, but this made it impossible to call this function multiple times.

Trying a solution from here Lifetime issue when shortening mutable slice - #2 by steffahn I was able to write this function:

fn extend(out_buf: &mut &mut [u8], data: impl AsRef<[u8]>) {
    let bytes = data.as_ref();
    let len = bytes.len();

    let buf: &mut [u8] = std::mem::take(out_buf);
    buf[0..len].copy_from_slice(bytes);

    *out_buf = &mut buf[len..];
}

But I don't understand exactly why this works.

My current reasoning is that getting a mutable reference from a mutable reference forces the lifetime to be narrowed, i.e:

let pp: &'small mut &'big mut u8 = ...;
let p = &'small mut u8 = *pp; /* cannot be &'big */

/* so once I write it back ... */
*pp = p; /* requires 'small: 'big */

But I don't understand why exactly this limitation exists.

UPD: Current example that is UB Rust Playground

13 posts - 2 participants

Read full topic

🏷️ rust_feed