Thanks!
Seems I gotta dig into the borrow checker before thinking too much about this!
Otherwise, compiling your code snippet is a nice illustration of how helpful the compiler tries to be ... lots of tips in the output there! To anyone else, just try running rustc
on this, with the second println!
uncommented and see the output, which is half error half linting.
For variables that are passed by reference, the ‘&’ is about whether the ownership of that memory address is transferred or not.
Yea. So if the second println!
were uncommented, how could we compile this? From what you've said, I'd guess that &
means "borrow" (ie, not "move" ownership).
So if we alter abc
to take a &String
type and not String
, and therefore only "borrow" the variable, and then pass in &v
and not v
to pass in a "borrowed" variable, it should compile.
fn abc(v: &String) {
println!("v is {}", v);
}
fn main() {
let mut v=String::from("ab");
v.push('c');
abc(&v);
println!("v is {}", v);
}
It seems to!
Of course, as the compiler suggests, we could instead just pass in v.clone()
which presumably creates a new variable and effectively "passes by value".
Digging in a bit more, what happens if abc
(tries to) mutate the variable?
We can add v.push('X')
to abc
and see if we get different printouts. As the compiler would tell us, we would need to make the argument v
mutable for this to work.
fn abc(mut v: String) {
v.push('X');
println!("v is {}", v);
}
fn main() {
let mut v=String::from("ab");
v.push('c');
abc(v.clone());
println!("v is {}", v);
}
// OUTPUT:
// v is abcX
// v is abc
I'm not clear on why I don't have to declare that the v.clone()
is mutable in anyway though.
What about trying the same with a "borrowed' variable?
Well we need mutable borrowed variables, so necessary adjustments to the types of abc
and its call in main
. And adding an additional mutation of v
in main
after abc
is called, and we get two different println outputs, with each mutation applying to the same variable.
fn abc(v: &mut String) {
v.push('X');
println!("v is {}", v);
}
fn main() {
let mut v=String::from("ab");
v.push('c');
abc(&mut v);
v.push('Y');
println!("v is {}", v);
}
// OUTPUT
// v is abcX
// v is abcXY