Skip to content

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

Closed
@netvl

Description

@netvl

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions