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

Bad / misleading error message with auto deref and mutable borrows of multiple fields #32930

Closed
TimNN opened this issue Apr 13, 2016 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. NLL-fixed-by-NLL Bugs fixed, but only when NLL is enabled. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@TimNN
Copy link
Contributor

TimNN commented Apr 13, 2016

Consider (playpen):

struct Foo {
    a: u32,
    b: u32,
}

struct Container {
    foo: Foo,
}

impl ::std::ops::Deref for Container {
    type Target = Foo;

    fn deref(&self) -> &Foo { &self.foo }
}

impl ::std::ops::DerefMut for Container {
    fn deref_mut(&mut self) -> &mut Foo { &mut self.foo }
}

fn main() {
    let mut c = Container { foo: Foo { a: 0, b: 0 } };

    {
        // let mut c = &mut *c; // uncomment to make it work
        let _a = &mut c.a;
        let _b = &mut c.b; // ERROR!
    }

    let mut d = Box::new(Foo { a: 0, b: 0 });

    {
        // let mut d = &mut *d; // uncomment to make it work
        let _a = &mut d.a;
        let _b = &mut d.b; // ERROR!
    }
}

Intuitively this should work since rust allows mutable borrows of disjoint fields however it does not because auto deref is involved.

The error message here is particularly bad / misleading for the Box case, in my opinion:

<anon>:34:23: 34:26 error: cannot borrow `d` (here through borrowing `d.b`) as mutable more than once at a time [E0499]
<anon>:34         let _b = &mut d.b;
                                ^~~
<anon>:34:23: 34:26 help: see the detailed explanation for E0499
<anon>:33:23: 33:26 note: previous borrow of `d` occurs here (through borrowing `d.a`); the mutable borrow prevents subsequent moves, borrows, or modification of `d` until the borrow ends
<anon>:33         let _a = &mut d.a;
                                ^~~
<anon>:35:6: 35:6 note: previous borrow ends here
<anon>:31     {
<anon>:32         // let mut d = &mut *d; // uncomment to make it work
<anon>:33         let _a = &mut d.a;
<anon>:34         let _b = &mut d.b;
<anon>:35     }

First found on reddit.

@TimNN
Copy link
Contributor Author

TimNN commented Apr 13, 2016

Related to #30104

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label Jul 25, 2016
@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 25, 2017
@Pauan
Copy link

Pauan commented Apr 19, 2018

I just ran into this with RefCell + borrow_mut (which in my opinion is a common situation). Thanks a lot for the &mut *foo workaround!

@shepmaster
Copy link
Member

The original example compiles successfully with NLL 🎉 .

@estebank estebank added the NLL-fixed-by-NLL Bugs fixed, but only when NLL is enabled. label Oct 15, 2018
@pnkfelix
Copy link
Member

NLL (migrate mode) is enabled in all editions as of PR #59114. Verified that test case compiled in Nightly 2015 edition; closing as fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. NLL-fixed-by-NLL Bugs fixed, but only when NLL is enabled. 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

7 participants