You'll get a compile-time error explaining the situation, yes, including documentation links and possible fixes. The differences between the versions are minimal.
fn add1(x: Thing) -> Thing {
x + 1
}
fn add2(x: &Thing) -> Thing {
x + 2
}
This works on the assumption that whatever "+ 1" really means doesn't itself need ownership of x, e.g. because it mutates it. If it does, then you'll get an error. Or you could do this:
fn add3(x: &mut Thing) {
x.add(3)
}
Which, presumably, modifies x instead of returning a copy. It's your job to make sure it makes sense to do that, but Rust has another trick in its pockets:
let y = add1(x); // Works; takes ownership.
let z = add2(&y); // Works, and doesn't take ownership.
let zz = add2(&y); // So you can do it twice. (Y tho?)
let h = add3(&y); // Compile-time error!
let hh = add3(&mut y); // Works. You need to specify that you're fine with y being mutated.
The first will take ownership of the thing you pass in, so you can't do something like this:
let x = vec![1, 2, 3];
let y = add1(x);
let z = add1(x); // error[E0382]: use of moved value: `x`
but the follow code is OK, because the function just borrows the value instead of owning (and destroying) it:
let x = vec![1, 2, 3];
let y = add1_borrow(&x);
let z = add1_borrow(&x);
This is legal too:
let x = vec![1, 2, 3];
let y = add1_borrow(&x);
let z = add1(x);
but as before you can't use x after this.
(Note, I chose Vec here because Vec does not implement Copy: if I used i32 it would just copy the value in the non-borrowing case, which would make the code fine as no ownership would be transferred.)
It won't compile, because the compiler keeps track of where you moved the value and notices that x now has no value. If you want the function to borrow the argument instead, make it take a reference, &x.