Question about the naming of &str and str

This is one of my earliest confusions about Rust. At first, when I saw the documentation:

A &str is made up of two components: a pointer to some bytes, and a length.

I thought that this might be a typo. The "fat pointer" must be str, and &str is just another layer of reference on top of the fat pointer.

Then naturally I became super confused about why the fat pointer str is a DST, and why another layer of indirection is needed.

Later, I saw that the book states:

...although a &T is a single value that stores the memory address of where the T is located, a &str is two values: the address of the str and its length.

I finally realized although &str is written as an ampersand in front of str, it is not a plain reference to a str, but rather a separate type. The fat pointer really is &str, not str. This seems a bit weird and inconsistent. :thinking: Why is str needed at all? Can't we just rename &str to str?

Thanks!

str needs to be placed behind a pointer, but & is not the only kind of pointer. &mut str, Box<str>, Arc<str>, Rc<str>, etc are all valid types that exist and are used in various places.

7 Likes

&str is not unique in that respect:

  • &[T] (slice) is also a fat pointer containing pointer and length.
  • &dyn T (trait object) is a fat pointer containing pointer and vtable-pointer.

And there might be others.

There are cases where the static type of the reference is missing important information about the referenced object. This information is then part of the reference as a kind of runtime metadata instead, which we call "fat pointer".

2 Likes

Here's another recent thread on much the same topic.

And here's an adaptation of something I said in a much older thread (the original was about making dyn Trait equivalent to Box<dyn Trait>):

(To be fair, Mutex<str> isn't a great example because it's not terribly useful, far less so than Mutex<dyn Trait>. I'll have to try to think of another example where str is useful inside an unsized wrapper.)

1 Like

Box<str>, maybe? AFAIK, it can be used just the same as Box<[T]> - as non-growable owned storage.

1 Like

Here's a very old Rust picture (beware! old!) Periodic table of Rust types, 2014: https://cosmic.mearie.org/2014/01/periodic-table-of-rust-types/

It lists the various str types. It says that Box<str> is "theoretical". Much like in the real periodic table, the table predicted something that would later be discovered to be an actual, practical type :wink: Because it fits into the pattern in the periodic table.

Since this was made, the Trait is now written dyn Trait for clarity.

2 Likes

I was thinking of cases where the wrapper itself is unsized (and must be used behind a pointer), such as Mutex<str> and RefCell<str>. (These are mostly not very useful because there's not too much you can do with a &mut str.)

I neglected to mention explicitly that all pointery types (e.g. Arc, &, &mut, Box, even Cow) work with unsized types as well as with sized ones, which is what makes them so well designed (and why a str type that was already a pointer would be far less useful). But I think it's great that even non-pointery types can be used generically to wrap something that is ?Sized.

str is the name for contiguous valid utf-8 in memory. Nothing else is known about the contents of a str, just that it's some amount of utf-8 in memory. However, you can't put that on the stack (Where any local variable goes) as though stack variables (currently) need to have a known size at all times. Hence, you need indirection to point at it.

To refer to a str, you need two components, which make up a "fat pointer". This occurs in any kind of pointer to str:

  • &str.
  • &mut str.
  • *const str.
  • *mut str.

And the types built on that:

  • NonNull<str>.
  • Box<str>.
  • Rc<str>.
  • etc.

The idea of unsized types can be kind of puzzling at times with slices (and string slices), however slices (and string slices) are just data, not a pointer to data, not a reference to data, they're just the continuous data in memory.

2 Likes

Thanks for all the helpful inputs! Although I still need time and experience to digest everything, my mental model of str and &str is much more correct and clear now.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.