I frequently encounter an issue when I am designing an allocation-free API that supports no_std with and without alloc, requiring the use of Cow.
The issue currently is, that Cow currently lives in alloc::borrow. So I have to choose between the API changing when activating alloc or design two different APIs with and without Cow.
Looking further into it, I discovered that alloc::borrow can actually live in core the only issue being coherence. As far as I am aware there is no concrete mechanism for the standard library to circumvent coherence rules in this case.
To be specific, the two problems are impl<T> ToOwned for [T] and impl ToOwned for str , which have to live in alloc .
What do you guys think, is this desirable? Is there an alternative solution? Thanks for @bjorn3 and @InfernoDeity for their help on Zulip.
And then have alloc's Cow be something like type Cow<'a, B, O = <B as ToOwned>::Owned> = core::borrow::Cow<'a, B, O>;.
That would let ToOwned still live in alloc, which is arguably appropriate since if you wanted your own alloc library you'd probably want your own ToOwned too, in order to get [T] -> YourOwnVec<T>.
Apparently there is #[rustc_incoherent_impl], so actually implementing it isn't the problem. But specialization will very likely interfere with that.
Considering I understand specialization only very poorly, I need to look into it to properly assess the scope of the problem here.
It doesn't make it local because coherence rules are not only about avoiding overlapping implementations but also about making sure that adding trait implementations with generic parameters on a type stays a non-breaking change.
It might be enough to kill the "breaking coherence here could/would be unsound due to specialization" argument though for this trait implementation.