…It’s a great abstraction, but only works for String.
Right now, String behaves like Arc with implicit Arc::make_mut calls in Rust, except for small and constant optimizations.
Note that str is an unsized type here, not a reference, and thus there is no double indirection. So Arc in this aspect is basically a template type (Arc<T: ?Sized>). The Sized trait in Rust has been room for a lot of confusion, so I am not sure if this is path Mojo should pursue. However, it allows for these neat optimizations, which in Mojo require a hardcoded library type with poor interoperability.
So now, where are the problems with Mojo’s approach. First of all, String’s invariant requires the storage to be UTF-8, thus requiring List[Byte] as storage. This leads to different performance characteristics just for opting out of UTF-8, and an extra conversion step.
Second, it requires Atomics for single threaded code, since there is no Rc<str> counterpart.
Solution sketch
String’s Cow logic is moved to a separate BytesStorage type and exposed via Bytes or ByteList, and of course, String. String remains the predominant type with Atomics whereas other byte types expose single threaded options.