Again and again I'm facing with discrimination of boxed slice.
Why here std::str::from_boxed_utf8_unchecked exist but no "checked" version? Because this chain:
std::str::from_boxed_utf8_unchecked was added in PR #41258, which initially also tried to add str::str::from_boxed_utf8, but it was later removed in the same PR due to this comment. The motivation is strange though considering that at the time there was String::from_utf8 and it simply returned the Vec in the error type.
The important thing is that String::from_utf8 doesn't take ownership of slice. It takes a reference and in case of failure you still have your slice and can do something about it.
On the other hand it's not clear what str::str::from_boxed_utf8 should do if you pass invalid slice. If it would just return a failure then invalid byte sequence would be lost. Or it can embed bad sequence into Result but that's very convoluted and hard to deal with API.
If you really need it you can easily implement it in your own code with the use of std::str::from_utf8 and std::str::from_boxed_utf8_unchecked.
Box<[u8]> → Vec<u8> is free, it just adds a capacity field matching the length
Vec<u8> → String is also free, as String is just a newtype
String → Box<str> is not free in general, but it is here because the first step put len == cap, and the second step didn't change it, so there's no shrink_to_fit needed.
Um, sorry? Returning Resultis the right way to design a fallible function. String's analogous FromUTF8Errordoes give you back the offending byte slice by-value, so there's no question as to whether this would be feasible with the identical API over boxed slices/strings.
But it's no overhead compared to what a "direct" / single-function Box<[u8]> -> Box<str> conversion would cost. That would also need to perform UTF-8 validation, in the exact same way that String::from_utf8() needs to.