-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Closed
Labels
A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regions
Description
#[crate_type="lib"];
struct List {
x: int,
next: Option<~List>
}
#[cfg(invalid)]
pub fn each_loop(mut thing: &mut List, f: |&mut int|) {
loop {
f(&mut thing.x);
match thing.next {
None => break,
// borrowck errors:
Some(~ref mut next) => thing = next,
}
}
}
pub fn each_rec(thing: &mut List, f: |&mut int|) {
f(&mut thing.x);
match thing.next {
None => {},
Some(ref mut next) => each_rec(*next, f),
}
}
each_loop
is invalid, but each_rec
is ok.
My feeling is that the loop form should be valid, since the thing
object is erased, and so the thing
and next
borrows do not overlap or alias (that is, the old object to which thing
pointed is inaccessible). However I could easily be wrong.
Allowing the first would allow us to write code that is guaranteed to be efficient; although LLVM does perform TCO often so it isn't completely necessary. (That said, LLVM doesn't TCO each_rec
, the closure seems to be interfering: with the closure call it is still recursive, but with just thing.x += 1
it is optimised to a loop)
(The equivalent thing with &
instead of &mut
is already valid.)
Metadata
Metadata
Assignees
Labels
A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regions