How compiler knows that ownership is moved?

In book (Polish translation of Rust book by Klabnik,Nichols)

    let s1 = String::from("hello");
    let s2 = s1;
    println!("{}, world!", s1);

error [E0382]: use of moved value: 's1'
--> src/main.rs:5:28
| let s2 = s1
| -- vale moved here

But if we modify:

    let mut s2 = "anything";
    if (random_or_user_choice)
    s2 = s1;

This information can be in runtime, but compiler can't know.

1 Like

What's your question? Yes, it is only known at runtime whether s1 is moved, so the compiler will conservatively assume that it was moved.

Also, in your second example, s1 is &str, which is Copy. This means moves don't invalidate the old location.

2 Likes

That is not true, it is known always in compile time that it is moved. Rust guarantee that everything is dropped when goes out of scope, so on compile time it is always known who is the owner of the variable.

But shared references are Copy so moves don't matter. If he had used String::from("anything") in his second example, then moves would matter.

Not if the move depends on a runtime conditional. Then the compiler can't know at compile time if the move occurred.

Rust will emit some flags which track the owner at runtime in these cases. These flags are generated by the compiler, and can only be accessed by the compiler.

1 Like

@KrishnaSannasi It depends on point of view. Semantically it does know that it is moved for the if expression, and outside of it is unavailable. Technically it need to actually store some flag on stack to know if it needs to be dropped at the end of scope, this is pretty much obvious.

Can be reference lifetime longer than lifetime borrowed object? How guarante that will not this?
What if reference is declared on block outer to object block ?

No, it can't, that's the entire point of the borrowing system. I don't really understand your question but if you were to do something like:

let outer = {
    let inner = String::new();
    &inner
};

then it won't compile and you will get an error like "inner does not live long enough".

Compiler does track some moves at run time too:

https://doc.rust-lang.org/nomicon/drop-flags.html

1 Like