3 ms·
Wouldn't closing a file handle be an action requiring mutability? If the file handle is just a integer then it would be copyable and ownership wouldn't come up
by Symmetry 10y ago
Wouldn't closing a file handle be an action requiring mutability? If the file handle is just a integer then it would be copyable and ownership wouldn't come up as an issue meaning discussions of safety would be moot.
I understand not trying to look at function bodies but the mutability of a function seems to be strictly a property of it's type signature.
But I think what really bothers me is that whether a value is actually passed to a function by pointer or by copying it onto the stack is governed by whether it has the 'copy' trait - not something obvious to the casual reader of the program. Silently converting what looks like a pass by value call to an in-practice pass by reference based on a trait definition elsewhere in the code base just seems excessively magical to me and I'd be much happier if the compiler threw an error at
let answer = add_first_element(v1, v2);
because pass by value requires the copy trait which Vecs v1 and v2 don't have.
- masklinn 10y ago> Wouldn't closing a file handle be an action requiring mutability? Closing a file requires ownership and is actually an RAII action: when the file object itself goes out of scope (which by definition means all extant references have been removed) the handle is closed. > But I think what really bothers me is that whether a value is actually passed to a function by pointer or by copying it onto the stack is governed by whether it has the 'copy' trait - not something obvious to the casual reader of the program. That's not correct. The Copy trait means it's semantically copied rather than moved so the original value can still be used, it does not change the technicalities of parameter passing which is always by-value (unless you're explicitly creating a reference) although things may then get optimised differently. > Silently converting what looks like a pass by value call to an in-practice pass by reference There's no such thing. Both Vecs are passed by value. Outside of method calls (which have some syntactic sugar) Rust requires references to be created explicitly. > I'd be much happier if the compiler threw an error at > let answer = add_first_element(v1, v2); > because pass by value requires the copy trait which Vecs v1 and v2 don't have. It has no reason to and it does not. `add_first_element` gets its argument by value, since Vec is not a Copy type v1 and v2 are thus moved into the function and not accessible anymore from outside it.
- Symmetry 10y ago>Closing a file requires ownership and is actually an RAII action: when the file object itself goes out of scope (which by definition means all extant references have been removed) the handle is closed. Ah, no wonder I misunderstood then. I'd forgotten that RAII was something Rust had and that feature does very nicely explain that design decision. I suppose the reason a Vec doesn't implement Copy then is that its members might not, like a file handle?
- masklinn 10y ago> I suppose the reason a Vec doesn't implement Copy then is that its members might not, like a file handle? That is correct, Vec has a pointer to a heap allocated buffer, meaning if Vec were Copy, you'd get two Vec structures for the same backing buffer and that's a recipe for disaster.
- pornel 10y ago> Wouldn't closing a file handle be an action requiring mutability? In Rust there is no distinction between mutable owned data and immutable owned data. There are only mutable/immutable references and bindings, but if you own the data, you can mutate it. fn foo(v: Vec) fn foo(mut v: Vec) are the same function. `mut` is not part of the type. Even the first function can do `let mut v = v` and make immutable owned `v` a mutable owned one (since Rust can guarantee there are no other references to it, so the mutation is not observable from outside). It's different from `&mut Vec`, which is a distinct type, and it mutably borrows the Vec. > If the file handle is just a integer That's why in Rust such values are wrapped in "newtypes" that don't allow copying, e.g. `struct Handle(i32)`. > pass by value call to an in-practice pass by reference Passing ownership of the `Vec` doesn't copy the items. Ownership/references and passing by value/reference are different concepts. `Box<Foo>` is an owned value, but it's implemented as a regular pointer (`Foo* ` in C). `&[Foo]` is a reference, but it's actually a small struct passed by value (`struct Ref {size_t len; Foo *data}` in C).
- Veedrac 10y agoCopy does _not_ affect compilation, only type checking. If you add Copy to a type, the generated code will not change. If you remove Copy from a type, the code will either stop compiling or be exactly the same. The difference between a copy and a move is whether you can still use the old value, and this is checked in the type system.