5 ms·
You've misinterpreted, it's not a question about reducing the annotation in a struct/enum definition, but about postponing the destruction of the String so that
by dbaupp 12y ago
You've misinterpreted, it's not a question about reducing the annotation in a struct/enum definition, but about postponing the destruction of the String so that the later references are valid, i.e. currently we have
fn test_parse_unsafe() {
let v = {
let text = "The cat".to_string();
tokenize_string3(text.as_slice())
}; // `text` destroyed here
assert_eq!(vec![Word("The"), Other(" "), Word("cat")], v);
}
but the suggestion/question is about changing this to
fn test_parse_unsafe() {
let v = {
let text = "The cat".to_string();
tokenize_string3(text.as_slice())
};
assert_eq!(vec![Word("The"), Other(" "), Word("cat")], v);
} // `text` destroyed here
so that the references in `v` are valid.
This could lead to "memory leaks", where a destructor is implicitly postponed to a higher scope, but I don't think it would be much of a problem in practice (the promotion would only be through simple scopes, not through loops, and maybe not through `if`s). In fact, there's an yet-to-be-implemented accepted RFC covering this[1] (there's no guarantee that it will be implemented though, just that the idea is mostly sound).
[1]: https://github.com/rust-lang/rfcs/blob/master/active/0031-better-temporary-lifetimes.md https://github.com/rust-lang/rfcs/blob/master/active/0031-be...
- asuffield 12y agoAh yes, that RFC is roughly what I had in mind, thanks. I believe that it's safe to promote through an if, although obviously not through a general loop.
- dbaupp 12y agoYes, I agree that it should be safe, I've softened my original text. However, it would require dynamically tracking if the destructor needs to be run, and there's currently discussion[1] about Rust possibly moving to a static model, for the highest performance. [1]: https://github.com/rust-lang/rfcs/pull/210 https://github.com/rust-lang/rfcs/pull/210
- asuffield 12y agoConsider this: On a two-way if statement, then a given storage location is either set on zero, one or both branches. If it is set on neither branch then the if statement is irrelevant and can be ignored. If it is set on one branch, then either it had an original value and hence can be treated as being set on both branches, or it must be destroyed within the branch of the if (no null pointers - think about it until it is clear that the type system guarantees this). Hence we are only interested in cases which are isomorphic with the location being set on both branches. We can treat this as a phi node following the if: there is one output value, which has been created in one of two different ways. In this case we don't know statically which value has been constructed, but we do know statically how and when to destroy it regardless of which one we get, because both branches have the same type and storage location. We don't actually need to know where it came from. Any obvious problems? I think it works...
- dbaupp 12y agoIt doesn't work, the &str could come from completely different types in the two branches. I.e. one branch could be created by .as_slice() on a String, the other could be created by referencing a global, e.g. let s = if cond { let some_string = create_it(); some_string.as_slice() } else { "literals are always-valid &str's" }; `some_string`s destructor should only be run if the first branch was taken.
- TheLoneWolfling 12y agoCouldn't the compiler get around that by introducing a boolean variable that is set depending on the branch of the if statement taken, that it checks before running the destructor? Although this starts getting really messy.
- dbaupp 12y agoYes, that's exactly how it would be handled, but it's then dynamic destruction, not static.
- 12y ago
- dllthomas 12y agoI like this - you can make sure something isn't named in subsequent code while still allowing it to be used. Ideally there could be some mechanism to statically assert that it is destroyed by some particular point, though I'm not sure what that should look like (I guess that's just making the lifetime explicit?).