Description
Right now trans introduces cleanup scopes at semi-arbitrary times. This was fine when first designed but now it is user visible because it affects the maximum lifetimes of values and hence causes errors in the borrow checker.
It interacts particularly poorly with @mut
freezes. For example, if I write:
let some_map: @mut HashMap<K,V> = ...;
let foo = *some_map.get(some_key);
this will cause some_map
to be frozen for the entire enclosing block rather than just the let foo
statement, because trans would not introduce a cleanup scope there. I at least issue a rather cryptic warning in this case (citing this issue #). The workaround is to introduce a block or a method:
// Option 1: add a method that combines the `*` and the call to `get` into one thing
// In this case, HashMap defines get_copy:
let foo = some_map.get_copy(some_key);
// Option 2: introduce a block and store the borrowed @mut into a local variable
let foo = {
let some_map = &mut *some_map;
*some_map.get(some_key)
};
We should permit cleanups after every expression exits. If we do this with the existing system, though, it'll cause a flood of basic blocks and jack up compilation times significantly. I want to modify the system so that rather than adding cleanups to a block scope, as we do now, you would instead associate cleanups with an expr id (in trans, I mean). The cleanup generation would thus be driven off the AST. I have added various FIXMEs in the code referencing this issue or #3511 where this might be relevant.