It's important to realize what happens with &s[1..5]
, and that it's &(s[1..5])
, namely, s[1..5]
is first first evaluated, this returns a value of type str
, and a reference to that value is taken. In fact, there's even more indirection: x[y]
in rust is actually syntactic sugar for *std::ops::Index::index(x,y)
. Note the dereference, as this function always returns a reference, which is then dereferenced by the sugar, and then it is referenced again by the &
in our code — naturally, the compiler will optimize this and ensure we are not pointlessly taking references to only dereference them again.
It so happens that the String
type does support the Index<Range<usize>>
trait and it's Index::output
type is str
.
It also happens that the str
type supports the same, and that it's output type is also str
, viā a blanket implementation of SliceIndex
.
On your question of auto-dereferencing, it is true that Rust has a Deref
trait defined on String
as well so that in many contexts, such as this one, &String
is automatically cast to &str
— any context that accepts a &str
also accepts a &String
, meaning that the implementation on Index<usize>
on String
is actually for optimization to avoid this indirection. If it not were there, the code would still work, and perhaps the compiler could even optimize the indirection away.
But that automatic casting is not why it works — it simply works because indexing is defined on many different types.
Finally:
I thought that the correct way to achieve this would be something like &((*str)[0..i]).
This would not work regardless, a &str
is not the same as a &String
and cannot be dereferenced to a String
like a &String
. In fact, a &str
in many ways is closer to a String
than it is to a &String
. a &str
is really just a fat pointer to a sequence of unicode bytes, also containing the length of said sequence in the second word; a String
is, if one will, an extra-fat pointer that also contains the current capacity of the buffer with it, and owns the buffer it points to, so it can delete and resize it.