Reputation: 437
The following test program would not compile:
fn f1( string: String) {
println!("{}", string );
}
fn f2( string: String) {
println!("{}", string );
}
fn main() {
let my_string: String = "ABCDE".to_string();
f1( my_string );
f2( my_string );
}
It generates the well-expected error:
11 | f1( my_string );
| --------- value moved here
12 | f2( my_string );
| ^^^^^^^^^ value used here after move
However, if you treat my_string
with the to_string()
method, the program compiles and works. to_string()
should be a no-op method since my_string
is a String
already. However, this programs works fine.
fn f1( string: String) {
println!("{}", string );
}
fn f2( string: String) {
println!("{}", string );
}
fn main() {
let my_string: String = "ABCDE".to_string();
f1( my_string.to_string() );
f2( my_string.to_string() );
}
How does the rust theory explain this paradox?
Upvotes: 4
Views: 363
Reputation: 437
The answer is that to_string()
applied to a String
is not a no-op; it is equivalent to clone()
. The clone returned by to_string()
is moved, whereas the original String
is only borrowed for cloning and is never moved.
I approve jthulhu's answer even though I'm not sure it points out the actual reason for the behavior.
Upvotes: 1
Reputation: 8657
The ToString::to_string
method requires a &str
, which is Copy
, therefore it can be moved out while keeping ownership (because &T: Copy
for T: ?Sized
, see the documentation).
On the other hand, String
does not implement Copy
, which means once the value is moved, its ownership has been given away.
Upvotes: 6