| Type | Owned alloc? | Accepts | Use when |
|---|---|---|---|
&str | No | string slices only | you only read, no conversion needed |
impl AsRef<str> | No | &str, String, Cow<str> | read-only, zero-cost generic |
impl Into<String> | Yes, on call | &str, String | you need to store/own it |
impl ToString | Yes, always | anything with Display | avoid — always allocates |
Cow<'a, str> | Sometimes | borrowed or owned | you want to delay allocation |
String | Yes | String only | explicit, just take ownership |
Practical rules:
- Just reading →
&strorimpl AsRef<str> - Need to own/store →
impl Into<String>(call.into()inside) - Avoid
impl ToString— it always allocates, useimpl Displayif you need formatting Cow<str>is niche — useful when you sometimes need to mutate/own and sometimes don’t
Most common correct pattern:
// read only
fn foo(s: impl AsRef<str>) {
let s = s.as_ref();
}
// store it
fn foo(s: impl Into<String>) {
let s = s.into();
}