Any expectation of overlapping blanket impls?

I was playing around with extending std::borrow::Cow and discovered that currently, std implements From<> for Cow<'a, T> for each potential type separately.

For example, std::string module explicitly implements a bunch of From traits for Cow<'a, str>:

impl<'a> From<&'a str> for Cow<'a, str> ...
impl<'a> From<String> for Cow<'a, str> ...
impl<'a> From<&'a String> for Cow<'a, str> ...

On the surface, it would be quite useful to instead have three very simple blanket impls instead:

impl<'a, T> From<&'a T> for Cow<'a, T>
    where T: ToOwned + ?Sized
{
    fn from(s: &'a T) -> Cow<'a, T> { Cow::Borrowed(s) }
}

impl<'a, T> From<<T as ToOwned>::Owned> for Cow<'a, T>
    where T: ToOwned + ?Sized
{
    fn from(s: <T as ToOwned>::Owned) -> Cow<'a, T> { Cow::Owned(s) }
}

impl<'a, T> From<&'a <T as ToOwned>::Owned> for Cow<'a, T>
    where T: ToOwned + ?Sized
{
    fn from(s: &'a <T as ToOwned>::Owned) -> Cow<'a, T> { Cow::Borrowed(s.borrow()) }
}

However, if you actually do this, rustc will rightfully complain that (a) first and third impls conflict over From<&_> for Cow<'_, _>, and (b) second impl conflicts with impl<T> From<T> for T.


It seems a quite unfortunate limitation.

First, it leads to proliferation of completely identical boilerplate code across std and other crates.

Second, it means that I can never (ergonomically) use Cow with third-party types/crates, unless the crate's author explicitly considers Cow and provides the necessary impls (because otherwise you run afoul of the orphan rules).

Is there any possible path forward for this problem? Is it expected that Rust will ever make it possible to write such overlapping impls (and get rid of all the boilerplate), or is this a fundamental limitation of Rust?

1 Like

Specialization would address some, but not all, cases. I doubt that or anything else is coming soon though.

Note that your example would also cause ambiguity by adding things like From<&'a str> for Cow<'b, &'a str> (which creates a Cow::Borrowed containing a &str), which doesn't exist today.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.