* I get the Zero-Cost explanation and I'm no performance-minded person, but I think there is an allocation in the Stack: slices are fat pointers as you show in the image, which are some 8 bytes I think. (from two 'u32' numbers)
* A question that I repeatedly struggle with is: Why don't we have "str" directly anywhere? My incomplete explanation is: We have vectors (Vec<T>), arrays([T;N]), and Unsized arrays ([T], actually called slices.); compared to arrays, slices are Unsized (they have runtime size, but no size **in the type**, as in [T; **N**]. Now, `str` is not the equivalent of Array but of a `[u8]` slice (Guarantees UTF8 items though!)^[1].
Thanks a lot for the thoughtful feedback and links! You are right about the typo, it should be &s1[..4], I’ll fix that. The Deref coercion reference is a great pointer. And yes, the “allocation” you mention is really just the slice metadata (pointer + length) on the stack, not a heap copy. About bare str, exactly, it is unsized so we only ever work with it through a reference. Really appreciate you taking the time to spell this out, I think others will find it super helpful too.
P.S. My post on Send and Sync got a lot of love on Reddit, you might enjoy that one as well if you have some time. Thanks again!
Thanks for the suggestion. `AsRef<str>` is great when you want to accept any “string-like” type, especially for public helpers or utilities that aim for flexibility and ergonomics for all callers.
For a simple `greet`, I stick with `&str`: it already works with `&String` and string literals, keeps the signature clear, and avoids generic monomorphization.
Great blogpost! I enjoyed the last one on Constructors and this one.
I've just some thoughts to share. Only the first one is a minor correction of a typo.
* The this section (https://blog.cuongle.dev/i/168300096/memory-layout-of-and-str) the line `let s2 = s1[..4];` has a typo, it should be `&s1[..4]`.
* More on Deref Coercion is here https://doc.rust-lang.org/nightly/reference/type-coercions.html#r-coerce.types.deref ...aka "Type Coercion at Coercion Sites." which means that Rust can do some type conversions in some specific places (mostly assignments). Remember there is `&mut str` as well :-) just as there is `&mut [T]`
* I get the Zero-Cost explanation and I'm no performance-minded person, but I think there is an allocation in the Stack: slices are fat pointers as you show in the image, which are some 8 bytes I think. (from two 'u32' numbers)
* A question that I repeatedly struggle with is: Why don't we have "str" directly anywhere? My incomplete explanation is: We have vectors (Vec<T>), arrays([T;N]), and Unsized arrays ([T], actually called slices.); compared to arrays, slices are Unsized (they have runtime size, but no size **in the type**, as in [T; **N**]. Now, `str` is not the equivalent of Array but of a `[u8]` slice (Guarantees UTF8 items though!)^[1].
The "slice" as in [T] can not exist in the Stack, only &[T] or &mut [T], because for that the type needs to be Sized, and they aren't. So &str, &mut str are either in RO memory or in the heap. In both cases we can only access through a pointer (`&`). What I explained is mostly from this link: https://stackoverflow.com/questions/54673145/why-can-fixed-size-arrays-be-on-the-stack-but-str-cannot, and less relevant https://stackoverflow.com/questions/63572130/why-are-string-literals-str-instead-of-string-in-rust)
^[1]: Sadly, "slice" is also used for &str, &[T] making it a mess (those are Sized, and take always 8 bytes!)
Thanks a lot for the thoughtful feedback and links! You are right about the typo, it should be &s1[..4], I’ll fix that. The Deref coercion reference is a great pointer. And yes, the “allocation” you mention is really just the slice metadata (pointer + length) on the stack, not a heap copy. About bare str, exactly, it is unsized so we only ever work with it through a reference. Really appreciate you taking the time to spell this out, I think others will find it super helpful too.
P.S. My post on Send and Sync got a lot of love on Reddit, you might enjoy that one as well if you have some time. Thanks again!
I think you should better
```
pub fn greet<S: AsRef<str>>(text: S) {
let name = test.as_ref();
println!("Hello, {}!", name);
}
```
Thanks for the suggestion. `AsRef<str>` is great when you want to accept any “string-like” type, especially for public helpers or utilities that aim for flexibility and ergonomics for all callers.
For a simple `greet`, I stick with `&str`: it already works with `&String` and string literals, keeps the signature clear, and avoids generic monomorphization.