Skip to content

Unboxed closures: cannot borrow data mutably in aliasable location #16668

New issue

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

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

Already on GitHub? # to your account

Closed
netvl opened this issue Aug 22, 2014 · 1 comment · Fixed by #18324
Closed

Unboxed closures: cannot borrow data mutably in aliasable location #16668

netvl opened this issue Aug 22, 2014 · 1 comment · Fixed by #18324
Labels
A-closures Area: Closures (`|…| { … }`) E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.

Comments

@netvl
Copy link
Contributor

netvl commented Aug 22, 2014

This code does not work very unexpectedly:

#![feature(unboxed_closures)]

struct Parser<I, O> {
    parse: Box<FnMut<(I,), Result<O, String>>>
}

impl<I, O:'static> Parser<I, O> {
    fn compose<K>(mut self, mut rhs: Parser<O, K>) -> Parser<I, K> {
        Parser {
            parse: box |&mut: x: I| {
                match self.parse.call_mut((x,)) {
                    Ok(r) => rhs.parse.call_mut((r,)),
                    Err(e) => Err(e)
                }
            }
        }
    }
}

The error:

<anon>:11:23: 11:33 error: cannot borrow data mutably in an aliasable location
<anon>:11                 match self.parse.call_mut((x,)) {
                                ^~~~~~~~~~
<anon>:12:30: 12:39 error: cannot borrow data mutably in an aliasable location
<anon>:12                     Ok(r) => rhs.parse.call_mut((r,)),
                                       ^~~~~~~~~
error: aborting due to 2 previous errors

When I expand this manually, I can get it to work:

#![feature(unboxed_closures)]

struct Parser<I, O> {
    parse: Box<FnMut<(I,), Result<O, String>>>
}

impl<I, O:'static> Parser<I, O> {
    fn compose<K>(self, rhs: Parser<O, K>) -> Parser<I, K> {
        struct ManualClosure<I, O, K> {
            this: Parser<I, O>,
            rhs: Parser<O, K>
        }

        impl<I, O, K> FnMut<(I,), Result<K, String>> for ManualClosure<I, O, K> {
            extern "rust-call" fn call_mut(&mut self, arg: (I,)) -> Result<K, String> {
                match self.this.parse.call_mut(arg) {
                    Ok(r) => self.rhs.parse.call_mut((r,)),
                    Err(e) => Err(e)
                }
            }
        }

        Parser { parse: box ManualClosure { this: self, rhs: rhs } }
    }
}

Though for some reason completely opaque to me I need to put 'static bound on O parameter, otherwise there is a compilation error:

<anon>:23:25: 23:67 error: value may contain references; add `'static` bound to `O` [E0149]
<anon>:23         Parser { parse: box ManualClosure { this: self, rhs: rhs } }
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

The original problem came from here.

@bkoropoff
Copy link
Contributor

The example now compiles with appropriate adjustments for language changes:

#![feature(unboxed_closures)]

struct Parser<I, O> {
    parse: Box<FnMut<(I,), Result<O, String>> + 'static>
}

impl<I, O:'static> Parser<I, O> {
    fn compose<K>(mut self, mut rhs: Parser<O, K>) -> Parser<I, K> {
        Parser {
            parse: box move |&mut: x: I| {
                match self.parse.call_mut((x,)) {
                    Ok(r) => rhs.parse.call_mut((r,)),
                    Err(e) => Err(e)
                }
            }
        }
    }
}

fn main() {}

Just needs a test now

@sfackler sfackler added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Oct 17, 2014
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 3, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-closures Area: Closures (`|…| { … }`) E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants