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

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

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 (`|args| { .. }`) 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: closures (`|args| { .. }`) 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