2 ms·
When you want a reference that can transparently become an owned value when mutated, Rust has a type Cow that implements this generally. It's an enum that has
by tene 5y ago
When you want a reference that can transparently become an owned value when mutated, Rust has a type Cow that implements this generally. It's an enum that has two variants, Owned and Borrowed. If you mutate a Cow::Borrowed, it first copies the data to a new owned allocation, and replaces itself with Cow::Owned.
However, the difference between String and &str has nothing to do with mutability, or whether the data is in a read-only page or not. If you have &mut str, you can mutate the values, and if you don't declare your String as mut, it's not mutable.
The difference is that String owns its allocation, whereas &str is a reference to memory that someone else owns. It's exactly the same as Vec vs &[u8], and if you check the source, you'll see that String is just a wrapper around Vec<u8>: https://doc.rust-lang.org/src/alloc/string.rs.html#278-280 https://doc.rust-lang.org/src/alloc/string.rs.html#278-280
The general principal is that if you own the allocation, you can reallocate it to change its size. If you only have a reference to memory that someone else owns, you can't do that.
Consider for example Go's slices, which work kind of like you describe, where they point to the original array's memory until someone grows the array, at which time they might or might not make a new allocation. Appending to a Go slice from some inner function can suddenly break code that calls it, because the slice it's operating on suddenly points to new memory.
Rust's Big Idea is to make ownership and borrowing more-explicit. Having your default stdlib text type be ambiguous about whether it's owning or borrowing is both weird, and also makes things a lot more awkward to deal with.
If you use Cow<str>, you'll see that its API declares that it borrows from some source, and can't outlive that source. That's fine if what it's borrowing from is static text in the binary, but that really constrains what you can do with a string that you've dynamically allocated.
Just like all other data structures, having a distinction between an owned value and a reference to the value is very useful. It's easy to build a variety of shared or ambiguous ownership structures on top of owned values and references, but it's much more complicated to go the other direction.