Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lifetime issues: assigning to a mutable reference with part of its current value #72477

Open
Ekleog opened this issue May 22, 2020 · 3 comments
Labels
A-lifetimes Area: lifetime related C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Ekleog
Copy link

Ekleog commented May 22, 2020

Edit: simplified reproducer as well as workaround available at #72477 (comment)

Hello,

While trying to implement an AsyncRead wrapper, I have hit something that I think is the borrow-checker being too restrictive with &mut inside Pin.

I originally thought it was an issue in pin-project, but @taiki-e pointed out that the issue also happens with raw Pin, in taiki-e/pin-project#226 (comment) (thank you!)

Copying the example here (with an explicit lifetime):

pub struct Foo<'a> {
    buf: &'a mut [u8],
}

impl<'a> Foo<'a> {
    fn foo<'b>(self: std::pin::Pin<&'b mut Self>) {
        self.buf = &mut self.buf[1..];
    }
}

(playground)

This is potentially related to #54934 ; but seeing as it manifests in a completely different way (ie. it doesn't manifest with just & references in the original example with pin-project linked above, though the example code here is incorrect indeed), I thought it'd be better to open another issue, as at worst it'd be fixed at the same time as #54934 and would just add another test.

As usual, thank you for all you do on this great language!

@Ekleog Ekleog added the C-bug Category: This is a bug. label May 22, 2020
@Ekleog Ekleog changed the title Custom AsyncRead / Futures implementations which hold a &mut Custom AsyncRead / Futures implementations which hold a &mut: lifetime issues with Pin May 22, 2020
@taiki-e
Copy link
Member

taiki-e commented May 22, 2020

I just found a way to avoid this issue in futures-rs repo: https://github.com/rust-lang/futures-rs/blob/71f1e054c2c85c38f28439392f1c291056051bd9/futures-util/src/io/read_exact.rs#L31-L34

playground

pub struct Foo<'a> {
    buf: &'a mut [u8],
}

impl<'a> Foo<'a> {
    fn foo(mut self: std::pin::Pin<&mut Self>) {
        let (_, rest) = std::mem::replace(&mut self.buf, &mut []).split_at_mut(1);
        self.buf = rest;
    }
}

@taiki-e
Copy link
Member

taiki-e commented May 22, 2020

Also, it looks like this issue can be reproduced without Pin.

playground

pub struct Foo<'a> {
    buf: &'a mut [u8],
}

impl<'a> Foo<'a> {
    fn repro(&mut self) { 
        self.buf = &mut self.buf[1..]; //~ ERROR
    }

    fn fixed(&mut self) {
        let (_, rest) = std::mem::replace(&mut self.buf, &mut []).split_at_mut(1);
        self.buf = rest;
    }
}

@Ekleog Ekleog changed the title Custom AsyncRead / Futures implementations which hold a &mut: lifetime issues with Pin Lifetime issues: assigning to a mutable reference with part of its current value May 22, 2020
@Ekleog
Copy link
Author

Ekleog commented May 22, 2020

Oooh, thank you for both your messages! I've been able to make my code compile with your workaround, and your reproducer is much simpler — I've just renamed the issue to better match the simplified reproducer you found, and will link to your message from the top post just after having posted this :)

(for the full context, I had two buffers, one of which was a borrow of the other, the solution was replacing the second buffer by a range that's to be interpreted as part of the first buffer)

@estebank estebank added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Feb 20, 2021
@Enselic Enselic added the A-lifetimes Area: lifetime related label Dec 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: lifetime related C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants