What is the idiomatic way to convert &str to String?

What is the most idiomatic way to convert a &str to a String?

Some options are:

15 Likes

I use String::from for static strings and to_owned() for others, but I've never thought hard about it. Looking at the options is giving me self-doubt.

5 Likes

Don't forget "hello".into()!

2 Likes

to_string just calls String::from, and String::from just calls to_owned. They're all inlined, so there's no performance cost to any of them. Format might be more expensive since it goes through all of the formatting abstractions.

11 Likes
2 Likes

As far as I'm aware, there's no performance difference between them, so use whichever you feel like.

If anything, the more interesting question is where those methods come from and why String has both of 'em. to_owned() is there because String implements std::borrow::ToOwned and to_string() comes from std::string::ToString.

The latter is particularly interesting, because the ToString trait is actually implemented for anything that implements Display. So you can do .to_string() on an i32 or on an Ipv4Addr or on your own type that you've implemented Display for.

Let's go over what each of these means semantically:

  • to_owned: I have a borrowed object and I want an owned version
  • to_string: I want the textual representation of something
  • into (or String::from): I want a generic type conversion
  • format!: I want a textual representation of something in a particular representation. Basically a fancy way of calling to_string (to_string is implemented generically for Display, the canonical way of using Display is through format!)

I think in most cases what you mean to do is to_owned. into is fine but conveys less intent. In cases where the type can be inferred, for example as a function argument, I think into is fine.

Don't use format! if you can use to_string, less overhead.

22 Likes

I'd say pick the one that best expresses the context in which you're trying to use it:

  • to_owned if you need a stronger level of access to it
  • to_string if you really want a string in particular
  • .into() if you're calling a function that needs something not quite what you have
  • etc
1 Like

I use only .to_owned(). I believe it is better to stick with a single option everywhere, if there are multiple equivalent choices. Among these choices, String::from is the most specific, but it's a mouthful to write and prefix, so I stick with .to_owned as the next one most specific.

As for idiomaticness, I believe there are two "warring camps" of "use .to_string() because it's simpler to teach", and "use .to_owned() because it is semantically more frugal" :slight_smile:

5 Likes

Here's what we decided to go with for the book :slight_smile:

7 Likes

IIRC there was a time in the past when to_string wasn't specialized, so to_owned was suggested because it was faster at the time. They're now both the same speed, though.

Kinda bummed to_owned wasn't chosen, since it helps you understand the distinction between str and String, as @dtolnay pointed out in his linked comment.

5 Likes