Skip to content

Pin can't borrow multiple fields mutable (even if type implements Unpin). #89982

@zvavybir

Description

@zvavybir
Contributor

Fields of Pin<&mut T> can't be independently borrowed from each other.

I tried this code:

struct TestStruct
{
    a: u8,
    b: u8,
}

fn t(mut ts: Pin<&mut TestStruct>)
{
    let x = &mut ts.a;
    let y = &mut ts.b;

    *y = *x;
}

I expected to see this happen: Nothing, it compiles fine.

Instead, this happened: I get the following error message:

 error[E0499]: cannot borrow `ts` as mutable more than once at a time
  --> src/main.rs:12:18
   |
11 |     let x = &mut ts.a;
   |                  -- first mutable borrow occurs here
12 |     let y = &mut ts.b;
   |                  ^^ second mutable borrow occurs here
13 | 
14 |     *y = *x;
   |          -- first borrow later used here

For more information about this error, try `rustc --explain E0499`.

I also think that the mut directly behind fn t is wrong, because I don't change the reference itself but that to which it points, but if I remove it rustc prints it's usual cannot borrow … as mutable, as it is not declared as mutable.

Meta

rustc --version --verbose:

rustc 1.57.0-nightly (4e89811b4 2021-10-16)
binary: rustc
commit-hash: 4e89811b46323f432544f9c4006e40d5e5d7663f
commit-date: 2021-10-16
host: x86_64-unknown-linux-gnu
release: 1.57.0-nightly
LLVM version: 13.0.0

It also doesn't work on current stable.

Activity

changed the title [-]`Pin` can't borrow multiple fields mutable (even if type if `Unpin`).[/-] [+]`Pin` can't borrow multiple fields mutable (even if type implements `Unpin`).[/+] on Oct 17, 2021
veber-alex

veber-alex commented on Oct 17, 2021

@veber-alex
Contributor

To get from the Pin to the inner TestStruct you go through the DerefMut trait.
The error is more clear if you write the code like this:

let x = &mut ts.deref_mut().a;
let y = &mut ts.deref_mut().b;

You can see that the second call to deref_mut happens while a mutable borrow from ts is still alive.
The solution here is to use DerefMut only once.

fn t(mut ts: Pin<&mut TestStruct>) {
    let d = &mut *ts;
    let x = &mut d.a;
    let y = &mut d.b;

    *y = *x;
}

Perhaps a better diagnostic message will help in situations like this.

zvavybir

zvavybir commented on Oct 17, 2021

@zvavybir
ContributorAuthor

Perhaps a better diagnostic message will help in situations like this.

That would be a good idea. Thank you!

added
A-diagnosticsArea: Messages for errors, warnings, and lints
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
and removed on Jul 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-pinArea: PinC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Enselic@ChrisDenton@veber-alex@zvavybir

        Issue actions

          `Pin` can't borrow multiple fields mutable (even if type implements `Unpin`). · Issue #89982 · rust-lang/rust