reem / rust-modifier

Convenient chaining APIs for free
29 stars 9 forks source link

Problem with closures #2

Closed bvssvni closed 10 years ago

bvssvni commented 10 years ago

play.rust-lang.org http://is.gd/2ZSWKi

pub trait Modifier<F> {
    /// Modify `F` with self.
    fn modify(self, &mut F);
}

/// A blanket trait providing the set and set_mut methods for all types.
pub trait Set {
    /// Modify self using the provided modifier.
    fn set<M: Modifier<Self>>(mut self, modifier: M) -> Self {
        modifier.modify(&mut self);
        self
    }

    /// Modify self through a mutable reference with the provided modifier.
    ///
    /// Note that this still causes a shallow copy of self, so can be
    /// slow for types which are expensive to move.
    fn set_mut<M: Modifier<Self>>(&mut self, modifier: M) -> &mut Self {
        modifier.modify(self);
        self
    }
}

impl<T> Set for T {}

pub struct Foo {
    text: String
}
pub struct Bar {
    text: String
}

impl Modifier<Foo> for Bar {
    fn modify(self, _: &mut Foo) {}
}

fn main() {
    let foo = Foo { text: "Foo".to_string() };
    let bar = Bar { text: "Bar".to_string() };
    let f = || {
        foo.set(bar);
    };
    f();
}

Error:

<anon>:41:9: 41:12 error: cannot move out of captured outer variable
<anon>:41         foo.set(bar);
                  ^~~
<anon>:41:17: 41:20 error: cannot move out of captured outer variable
<anon>:41         foo.set(bar);
                          ^~~
error: aborting due to 2 previous errors
playpen: application terminated with error code 101
bvssvni commented 10 years ago

I have found a workaround for piston-current.

reem commented 10 years ago

@bvssvni: move || should fix this.

EDIT: Oh, never mind. You need full unboxed closures for FnOnce or you must use a proc because they take by-value receivers so can move out of outer vars.