2

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?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
Kalle Svensson
  • 353
  • 1
  • 10
  • 1
    Passing `my_string` by value moves it. Calling `my_string.to_string()` only borrows the string and returns a different string as a copy. – alter_igel Dec 15 '22 at 16:29
  • 1
    @alter_igel: thank you. Yes, it must be correct because I can replace ```to_string()``` with ```clone()``` and get the same effect. Why you don't make it the answer so I will accept it. Add a comment that ```to_string()``` and ```clone()``` are equivalent in this case? – Kalle Svensson Dec 15 '22 at 16:36
  • 1
    @kmdreko: thank you. This tittle is a lot better! – Kalle Svensson Dec 15 '22 at 16:42

2 Answers2

5

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.

jthulhu
  • 7,223
  • 2
  • 16
  • 33
0

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.

Kalle Svensson
  • 353
  • 1
  • 10