hax icon indicating copy to clipboard operation
hax copied to clipboard

`FnMut` closures are not supported yet

Open franziskuskiefer opened this issue 1 year ago • 4 comments

In the code below, the test_fails functions throws errors, while test_works is fine.

struct Test {
    k: Option<u8>,
    y: u8,
}

impl Test {
    fn test_works(&mut self) {
        match self.k.take() {
            Some(k) => {
                self.y = 5;
            },
            None => (),
        }
    }

    fn test_fails(&mut self) {
        self.k.take().map(|k| {
            self.y = 5;
        });
    }
}

Open this code snippet in the playground

franziskuskiefer avatar Oct 28 '24 21:10 franziskuskiefer

I think it is reasonable to fail on test_fails and not on test_works because the mutation of self happens inside a closure in test_fails. Those two implementations look similar in the Rust world but if you try to "functionalize" this mutation this means the closure must return the new value of self, but then that would not go well with the closure type expected by map.

maximebuyse avatar Nov 07 '24 13:11 maximebuyse

Does that mean that we do not currently support mutation within map? If so, that would be good to document.

karthikbhargavan avatar Nov 07 '24 15:11 karthikbhargavan

Does that mean that we do not currently support mutation within map? If so, that would be good to document.

Yes, except maybe if the mutation is on the argument of the closure.

maximebuyse avatar Nov 07 '24 15:11 maximebuyse

Ah yes, thanks @maximebuyse, somehow I missed that closure! Clearly, we do not support mutable closures (aka FnMut).

Some quick notes on supporting FnMuts:

  • normal closures to FP is great, the capture is a primitive feature of our target languages
  • some of our backend cannot support lambdas
  • in presence of FnMut, the environment becomes something we don't want only to consume but also to mut.
  • calling an FnMut requires the fn to be &mut

W95Psp avatar Nov 12 '24 09:11 W95Psp