Search code examples
stringrustconcatenation

Why can't I concatenate two Strings together, but I can concatenate a String and a &str?


The Rust Book, Chapter 4 under "Ways Variables and Data Interact: Clone" says you can use .clone to set s2 to s1 like this

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

Why can't I change s2 to be s1.clone() + s1.clone()

let s1 = String::from("hello");
let s2 = s1.clone() + s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

When I try to compile that, I get

error[E0308]: mismatched types
 --> src/main.rs:3:24
  |
3 |     let s2 = s1.clone() + s1.clone();
  |                           ^^^^^^^^^^
  |                           |
  |                           expected `&str`, found struct `String`
  |                           help: consider borrowing here: `&s1`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `comment` due to previous error

I realize I can fix the second part by changing s1.clone() to &s1.clone(), but why is this required?


Solution

  • The Add instance for strings takes a String on the left and a &str on the right. This consumes the string on the left and extends it with (a copy of) the string on the right. It does this for efficiency reasons, to avoid having to copy both strings in every case.

    So when you want to concatenate two strings in Rust with +, the left-hand side needs to be a String (an owned string) and the right-hand side needs to be a &str (a borrowed string slice). So consider

    let s2 = s1.clone() + &s1.clone();
    

    or, since we're borrowing it, there's no need for the second clone at all.

    let s2 = s1.clone() + &s1;