graydon/rust — Issue #1261: bind allows data to be moved multiple times
Author: nikomatsakis
Created: 2011-12-06 02:00:47+00:00
State: open

This code crashes today

```
// 'x' can have any mode but & or &&
fn foo(-x: ~int) { }
fn main() {
let b = bind foo(~3);
b();
b();
}
```

The error is that bind needs to "re-copy" the ~3 each time `b()` is invoked, but it doesn't. In other words, that bind code is equivalent to `let x = ~3 in fn () -> foo(x)` (in some weird O'Caml/Rust hybrid) but it would need to be `fn() -> let x = ~3 in foo(x)` to be safe.

Not sure the best fix here. One thought is to ensure that bind `let b = bind f(E1, ..., En)` is syntactic sugar for something like:

```
let b = {
let v1 = E1;
...
let vN = En;
lambda() { f(v1, ..., vN) }
}
```

Similarly, upvars in lambdas should have reference mode (referencing the environment, not creator stack frame) which would prevent moves.