I’ve been messing with some custom string types - in particular, stack-allocated small strings like InlinableString, smallstr and arrayvec::ArrayString. I’ve noticed that in each case I’ve tried, the following shape of code doesn’t compile:
let s: SmallString<[u8; 8]> = SmallString::from("foo"); // This is fine let borrowed: Cow<str> = Cow::Borrowed(&*s); assert_eq!("foo", borrowed); // This blows up let owned: Cow<str> = Cow::Owned(s); assert_eq!("foo", owned);
error[E0271]: type mismatch resolving `<str as std::borrow::ToOwned>::Owned == string::SmallString<[u8; 8]>` --> src/string.rs:970:31 | 970 | let owned: Cow<str> = Cow::Owned(s); | ^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `string::SmallString` | = note: expected type `std::string::String` found type `string::SmallString<[u8; 8]>`
I’ve tried a few variants but can’t make it work.
Why is this? All these types implement
Clone - why isn’t that enough?
Is there a straightforward fix - either implementing some missing trait for
SmallString etc, or setting up the Cow::Owned differently?
Absent a solution, when optimizing some string manipulation, it seems I have to chose between getting copy-on-write behavior / avoiding unnecessary allocations, and making allocations on the stack when they’re necessary. Which is unfortunate.