rust-lang/rust — pull request #17784 by bkoropoff (2014-10-05 00:56:16+00:00)
Title: Don't allow Fn unboxed closures to mutate upvars

This fixes a soundness problem where `Fn` unboxed closures can mutate free variables in the environment.
The following presently builds:

```rust
#![feature(unboxed_closures, overloaded_calls)]

fn main() {
let mut x = 0u;
let _f = |&:| x = 42;
}
```

However, this is equivalent to writing the following, which borrowck rightly rejects:

```rust
struct F<'a> {
x: &'a mut uint
}

impl<'a> Fn<(),()> for F<'a> {
#[rust_call_abi_hack]
fn call(&self, _: ()) {
*self.x = 42; // error: cannot assign to data in a `&` reference
}
}

fn main() {
let mut x = 0u;
let _f = F { x: &mut x };
}
```

This problem is unique to unboxed closures; boxed closures cannot be invoked through an immutable reference and are not subject to it.

This change marks by-reference upvars of `Fn` unboxed closures as freely aliasable in mem_categorization, which causes borrowck to reject attempts to mutate or mutably borrow them.

@zwarich pointed out that even with this change, there are remaining soundness issues related to regionck (issue #17403). This issue affects boxed closures as well.