Difference between str and String

I have a beginner question as I have started learning rust. I can't really get the difference between the type str for literals and the type String.
1/ Why can't we declare slices as String?
2/ Why can we pass string literals directly and not as reference to a function like in the example below:

`fn my_fun(s: &str){
....
}

fn main(){
let s = "something";
my_fun(s); //correct
my_fun(&s); //also correct
}
`

Thanks.

This is most definitely a super common question. Perhaps you can get more and better information faster by just googling for "rust str vs string". Which oneĘĽs the best explanation for you probably depends on your what your previous programming knowledge is. Perhaps someone else wants to link a particularly good explanation one can find online.

To answer your particular questions:

The type str is the type of string slices. So I probably need to call you out on calling it just the type of string literals because that's inaccurate. The question that remains is why string slices are something else that String, but thats just the general "what's the difference between those" question.

String literals live in static immutable memory. When you pass a literal it is always already a reference to str. If you now take a reference of that, that's the type &&str and there are coercion rules that allow this type to be converted back into &str implicitly by dereferencing.

2 Likes

There's a good post somewhere, but I can't find it, so I wrote something instead:

The difference between &str and String is that the first borrows string data stored by some other variable, and String has ownership of some string data. You can't declare a &str as String, as a &str doesn't have any ownership it could give to the String. You can still copy the string data with String::from(...) to create a separate owned version though.

As for "something", whenever you write a string literal in the code, that's shorthand for declaring an immutable global variable containing the bytes of the string. The string literal then becomes a reference to that global. You don't need an & when passing a string slice because it's already a reference (to a global).

2 Likes

Lots of terminology aside:

String = growable collection of text
str = fixed size text

A good comparison:
String is to Vec as str is to array.

That's partly why you see str passed as &str (to avoid copying).

String literals are baked into the executable and are of type &'static str as the text only exists in one location and is referenced everywhere it is used.

2 Likes

Thanks for providing a clue to this surprising behavior - I've wondered before why & is sometimes optional. Is there a way to get the compiler to explain when it is doing this sort of coercion. And can someone point to the rules for when it is allowed, or an explanation as to why this sort of ambiguity is allowed?

1 Like

Well, I wouldn’t bet on the compiler explaining this anytime soon, but the reference can give you all the details. I posted an explanation about why &String coerces to &str here, so please read through it:

The situation here very similar since &T implements Deref with Target = T ⟶ here, and thus &&T coerces to &T.


In case that isn’t clear, the & is not “optional” in the sense of “you kind of need it but it can be left implicit”. What OPs code example does is add a redundant & that doesn’t hurt because of the implicit de-referencing that reverses its effect. In my view, this situation it is more of an optional * or .deref() than an optional &.

Also, & is rarely optional in situations where you really need to create a reference. The only place I can think of is method call receivers, so that you wouldn’t need to write (&x).method() instead of x.method() when method takes a &self and x is not a reference already. If you’re also interested in more information about referencing and dereferencing of method receivers, you can read this page of the reference.

In the case of string literal, the literal itself already has type &'static str, that’s why you don’t need to write any &.

3 Likes

You're not alone in that. Here's my favourite blog post about the difference:

(cleverly disguised as being about fizzbuzz)

1 Like