Skip to content

Borrow scope for pattern matches - again #68934

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

Open
axos88 opened this issue Feb 7, 2020 · 4 comments
Open

Borrow scope for pattern matches - again #68934

axos88 opened this issue Feb 7, 2020 · 4 comments
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@axos88
Copy link

axos88 commented Feb 7, 2020

This issue seems to be similar to this one, but the referenced issue #6379, does not solve it:

playground

enum Either<A,B> {
    Left(A),
    Right(B)
}

enum Tree<'a, A, B> {
    ALeaf(A),
    BLeaf(B),
    ABranch(&'a mut Tree<'a, A, B>, A),
    BBranch(&'a mut Tree<'a, A, B>, B)
}

impl<'a, A: PartialOrd, B> Tree<'a, A ,B> {
    fn deep_fetch(&mut self, value: Either<A, B>) -> Result<&mut Self, (&mut Self, Either<A,B>)> {
        match (self, value) {
            (Tree::ABranch(ref mut a, ref v), Either::Left(vv)) if v > &vv => {
                a.deep_fetch(Either::Left(vv))
            }

            (this, _v) => Err((this, _v))
        }
    }
}
error[E0505]: cannot move out of `_` because it is borrowed
  --> src/lib.rs:20:14
   |
14 |     fn deep_fetch(&mut self, value: Either<A, B>) -> Result<&mut Self, (&mut Self, Either<A,B>)> {
   |                   - let's call the lifetime of this reference `'1`
15 |         match (&mut *self, value) {
16 |             (Tree::ABranch(ref mut a, ref v), Either::Left(vv)) if v > &vv => {
   |                            --------- borrow of value occurs here
17 |                 a.deep_fetch(Either::Left(vv))
   |                 ------------------------------ returning this value requires that borrow lasts for `'1`
...
20 |             (this, _v) => Err((this, _v))
   |              ^^^^ move out of value occurs here
@axos88
Copy link
Author

axos88 commented Feb 7, 2020

It is also odd that if the pattern guard is removed, the compiler complains about mixing by ref and by move bindings.

@axos88
Copy link
Author

axos88 commented Feb 7, 2020

If Copy is added to A, vv is bound by ref, and dereferenced (copied) when returned, then it compiles or not based on wether a match gueard is present.

@axos88
Copy link
Author

axos88 commented Feb 7, 2020

Compiles:

impl<'a, A: PartialOrd + Copy, B> Tree<'a, A ,B> {
    fn deep_fetch(&mut self, value: Either<A, B>) -> Result<&mut Self, (&mut Self, Either<A,B>)> {
        match (self, value) {
            (Tree::ABranch(ref mut a, ref v), Either::Left(ref vv)) => 
                a.deep_fetch(Either::Left(*vv)),

            (this, _v) => Err((this, _v))
        }
    }
}

Doesn't:

impl<'a, A: PartialOrd + Copy, B> Tree<'a, A ,B> {
    fn deep_fetch(&mut self, value: Either<A, B>) -> Result<&mut Self, (&mut Self, Either<A,B>)> {
        match (self, value) {
            (Tree::ABranch(ref mut a, ref v), Either::Left(ref vv)) if v == vv => 
                a.deep_fetch(Either::Left(*vv)),

            (this, _v) => Err((this, _v))
        }
    }
}

@matthewjasper matthewjasper added the NLL-polonius Issues related for using Polonius in the borrow checker label Feb 7, 2020
@axos88
Copy link
Author

axos88 commented Feb 7, 2020

Even simpler repro:

struct UBranch<'a>(&'a mut UBranch<'a>, u32);

impl<'a> UBranch<'a> {
    fn deep_fetch(&mut self, v2: u32) -> &mut Self {
        match self {
            UBranch(ref mut a, ref v) if v == &v2 => a.deep_fetch(v2),
            x => x
        }
    }
}

@fmease fmease added A-borrow-checker Area: The borrow checker T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. and removed NLL-polonius Issues related for using Polonius in the borrow checker labels Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. 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

3 participants