`to_string()` vs `to_owned()` for string literals

I've seen both to_string() and to_owned() used for converting a string literal into a String. What are the differences between these two options, and when should you use which one?

16 Likes

You should always be using to_owned(). to_string() is the generic conversion to a String from any type implementing the ToString trait. It uses the formatting functions and therefor might end up doing multiple allocations and running much more code than a simple to_owned() which just allocates a buffer and copies the literal into the buffer.

41 Likes

I'm more fond of using .into(). It requires adding type hints in some cases, but for most cases it is shorter than the alternatives. Especially when passing a string literal to a function that requires String.

4 Likes

This may be fixed in the future with specialization, as str could implement ToString directly instead of having it go through the generic impl<T> ToString for T where T: Display {} implementation, which employs the formatting framework. But currently I do concur with your recommendation.

9 Likes

Now that specialization for str::to_string() has landed, we can safely say that to_string() has the same performance as to_owned(), and thus to_string() should be used since it's more clear

38 Likes

I found that my opinion on this has changed significantly over the past 12 months as I have grown more experienced with Rust.

I now strongly prefer to_owned() for string literals over either of to_string() or into().

What is the difference between String and &str? An unsatisfactory answer is "one is a string and the other is not a string" because obviously both are strings. Taking something that is a string and converting it to a string using to_string() seems like it misses the point of why we are doing this in the first place, and more importantly misses the opportunity to document this to our readers.

The difference between String and &str is that one is owned and one is not owned. Using to_owned() fully captures the reason that a conversion is required at a particular spot in our code.

struct Wrapper {
    s: String
}

// I have a string and I need a string. Why am I doing this again?
Wrapper { s: "s".to_string() }

// I have a borrowed string but I need it to be owned.
Wrapper { s: "s".to_owned() }
86 Likes

Not if you mentally read to_string as to_String :slight_smile:

5 Likes

For you, okay. But, someone else down the line, probably much less experienced than you, will be trying to read and understand your code, so clear intent is very helpful. (And, sometimes that less-experienced person is you, six months -- or five years -- later.)

2 Likes

Is there an explanation somewhere why you would turn a &str to String (other than make the borrow checker stop nagging)?

  1. To be able to change the string or to ensure that the string stays alive.
  2. Please don't post on old topics and instead create a new topic.
4 Likes

This topic was automatically closed after 16 hours. We invite you to open a new topic if you have further questions or comments.