Hacker News new | ask | show | jobs
by nerdponx 2445 days ago
Is there any kind of compile-time check available for this (e.g. BIG COMPILER WARNING when you pass-by-value something that lacks Copy)? Seems like a lot of unsettlingly Python-esque freedom ("read the docs and don't screw up") for a language like Rust.
3 comments

No, passing a "moved" structure by value is perfectly safe, fine and normal. All it means is that you won't be able to reuse it afterwards unless the function you're calling returns it.

There is no "read the docs and don't screw up" because the program will not compile at all if you do it wrong, and the compiler will explain why.

It's very useful for data ownership e.g. move file or string, you can forget about its existence (you have to really). It's also extremely useful to encode "static" state machines, especially when they're attached to some sort of unique resource: on state transition, consume the old state (one type) and return the new state (a different type). Not all state machines can be encoded thus and still useful, but when they do it's really nice.

It is perfect fine to take by value something that is not Copy to transfer its ownership.

It is a compiler error to use the value after it was moved. And the compiler error is quite explicit about how to solve it

For example you can explicitly clone

    let y = add(x.clone());
    let z = add(x);
What would be cases where the add() function need ownership of the x?

What the chance in real life that a function like that cannot simply use a reference?

In my learning Rust, my life became significantly better and easier when I started to references to borrow as much as possible.

That was just an example. But maybe 'x' is a BigInt type that use a memory allocation to store its contents. The ownership would be transferred to the return value
But again, what would be the drawback(s) of using a pointer instead of transfering the ownership?

Not rethorical, I'm genuinely curious as I used to struggle with the copy vs move decisions, and a bunch of issues with ownership which went all away when I started using pointer/borrowing everywhere.

The downside to using a mutable reference instead of passing around ownership is just that it would be awkward.

You'd have to write two extra lines of code to set up y and z separately from calling add(), and you'd have to make them mutable which is an extra mental burden.

And an immutable reference is bad because it would force extra objects to be allocated, wasting time and cache space.

Rust really doesn't do ("read the docs and don't screw up").

It's a very much a "bondage and discipline"-style language in the sense that unless you explicitly use "unsafe", you have to prove to the compiler that everything you do is safe. Moving large things is not unsafe because after you move something to a different scope, the original doesn't exist anymore and can't be used, so if you were to accidentally move something and tried to use it again, the compiler would helpfully tell you that the thing you're trying to refer to isn't there anymore.

There is no warning on every time you pass something without copy because passing things to different scopes is extremely common, normal and desired.