3 ms·
> it seems like the most flat-footed approach to preventing double-frees (never let two functions access the same memory, even those that can be trivially prove
by wtetzner 9y ago
> it seems like the most flat-footed approach to preventing double-frees (never let two functions access the same memory, even those that can be trivially proven to run sequentially)
This might just be a case of needing non-lexical lifetimes. I'm not sure about that, because I don't know the details of what issues you ran into.
> Beyond that, when defining a struct type that holds a reference, you have to know at definition time the lifetime of that reference, even it may vary from instance to instance (sometimes I want the struct to own the reference, but sometimes I don't).
The main issue I run into is when I want a struct to own a value, and for that struct to also include a reference into that value.
- weberc2 9y ago> This might just be a case of needing non-lexical lifetimes. I'm not sure about that, because I don't know the details of what issues you ran into. I don't think the issue is about lexical lifetimes, but I don't have a very good understanding of what that means, either. My issue is that I frequently want to take some data and pass it into two separate functions, but I can't do this unless those functions are designed to take the value by reference. Even if those values contain owned references into the heap, the programs can be trivially proven to be correct. I can work around this by always passing references, but it seems strange to use reference semantics when all I really want is to not destroy the original value. Another common case is that I have a borrowed reference that points to data I would like to pass (by value) into another function: `fn foo(bar: &Bar) { baz(bar.x) }`.
- wtetzner 9y ago> Even if those values contain owned references into the heap, the programs can be trivially proven to be correct. I don't think that's true. Passing data to a function when it's not a reference means that you're giving ownership to that function. How could you then pass it to another function (unless the first returned it again)? Once a function has ownership, it means nothing else has ownership of the data. Basically, if you write a function that just takes a value, and doesn't take a reference, then you're telling your callers to give you ownership. If you don't want to take ownership, then just always accept a reference. Maybe I'm misunderstanding the problem you're having. Do you have an example of another language that lets you do what you want?
- weberc2 9y ago> Passing data to a function when it's not a reference means that you're giving ownership to that function. Only in Rust, but there's no apparent reason to move ownership. If Rust didn't move ownership during pass-by-value, it would still be trivial to prove the following code correct: fn main() { let x = String::new(); foo(x); bar(x); // x is destroyed } > Maybe I'm misunderstanding the problem you're having. Do you have an example of another language that lets you do what you want? Here's the equivalent in C++: int main() { std::string x = ""; foo(x); bar(x); // x is destroyed }
- wtetzner 9y ago> Here's the equivalent in C++: > int main() { std::string x = ""; foo(x); bar(x); // x is destroyed } Doesn't C++ do a copy in this case?
- weberc2 9y agoIt does; that's the point: you can copy without losing safety guarantees, so there's no obvious reason to use an affine type system.
- wtetzner 9y agoYou can copy in Rust too. You just call .clone(), or if you want your type to always be copied, have it implement the Copy trait. In that case, it does exactly what you want. But Rust is more explicit about copying in general, to make it harder for the performance cost to be hidden.
- mathw 9y agoIf those two functions both need to own the data you're passing in, then they should take it by value, because in Rust passing by value means giving ownership of the data to the thing you're passing it to. It might give it back (as a return value), but that's another matter. If a function only needs to use some data for a bit, it should borrow it i.e. pass by reference. And if you need to give ownership of some data to a function, and you also need that data for something else, you have to copy it, so that you can give one copy to a function to do what it wants with, and keep the other one for your own purposes.