From trait conflicting between `bool` and `Cow<str>`

Hi folks!

Please, why is From<bool> conflicting with From<T: Into<Cow<'a, str>>>??

use std::borrow::Cow;

#[derive(Debug, Default)]
struct Repr<'a> {
    unit: Cow<'a, str>,
    sep: Option<bool>,
}

impl<'a, T> From<T> for Repr<'a>
where
    T: Into<Cow<'a, str>>,
{
    fn from(unit: T) -> Self {
        Self {
            unit: unit.into(),
            ..Self::default()
        }
    }
}

impl From<bool> for Repr<'_> {
    fn from(sep: bool) -> Self {
        Self {
            sep: Some(sep),
            ..Self::default()
        }
    }
}

fn main() {
    // error[E0277]: the trait bound `Cow<'_, _>: From<bool>` is not satisfied
    // println!("{:?}", Cow::from(true))
}

It gives this error:

error[E0119]: conflicting implementations of trait `From<bool>` for type `Repr<'_>`
  --> src/main.rs:21:1
   |
9  | / impl<'a, T> From<T> for Repr<'a>
10 | | where
11 | |     T: Into<Cow<'a, str>>,
   | |__________________________- first implementation here
...
21 |   impl From<bool> for Repr<'_> {
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Repr<'_>`
   |
   = note: upstream crates may add a new impl of trait `std::convert::From<bool>` for type `std::borrow::Cow<'_, str>` in future versions

I'm trying to write something along the lines of Pattern in std, but with a method that receives repr: impl Into<Repr<'a>> and some different From impls for it.
Playground: Rust Playground
Thank you!

I'm on the phone right now, so I'm sorry in advance for not searching the implementation for you, but this error means that bool implements Into<Cow<'a, str>>, therefore your implementations conflict with each other.

This cannot be fixed without specialization being stabilised.

Thanks @firebits.io, I thought so too!
But I tried it, and it seems Cow doesn't have such impl...

    // error[E0277]: the trait bound `Cow<'_, str>: From<bool>` is not satisfied
    println!("{:?}", Cow::<str>::from(true))

Interesting. I have tried to find any possible conflicting implementation, but haven't found any.

1 Like

Yep. So, why does the playground fail? Weird, isn't it?

Note the note:

note: upstream crates may add a new impl of trait
`std::convert::From<bool>` for type `std::borrow::Cow<'_, str>`
in future versions

If your implementation was allowed, it would become a semver breaking change for std to add that implementation (it would break your crate and any dependencies of it). The error is to prevent you from imposing such a restriction on upstream.

I.e. it's not just about existing implementations.

4 Likes

Ah, gotcha. So it's complaining that such implementation might exist in the future, which would break this code.

Hi @quinedot! Great to see you here.

Humm, but I don't try to implement From<bool> for Cow, I implement it for a local type, which will call Cow::default()... I still fail to see why it breaks.

Rust doesn't allow overlapping implementations, and if std added From<bool> for Cow<'_, str>, then

More generally, the overlap check won't assume that "T doesn't implement Trait<..>" must hold unless it is both currently true, and impl T for Trait<..> is also allowed under the orphan rules.[1]

You can't implement Into<Cow<'_, str>> for bool due to the orphan rules, so for the purposes of the overlap check, the compiler assumes upstream may one day implement it (in the same major SemVer).

(This may become more flexible in various ways eventually, but that's probably a long way off and may or may not apply to your specific situation.)


  1. As described here. ↩ī¸Ž

6 Likes

Awesome, I got it now, thank you!

So, there isn't really any way to do this, right?
I like Into parameters so I can call f(1) or f(None) for a fn f(t: impl Into<Option<i32>>).
Here, I was trying f("bytes") and f(true) for a fn f(r: impl Into<Repr>).

No great way, but you could use a bunch of non-blanket implementations.

1 Like

Ahh, I see! That does solve it.

Thank you again, @quinedot.
Thank you @firebits.io too.

2 Likes

you can use a macro to generate such implementations:

macro_rules! impl_from_for_repr {
    ($($t:ty => $field:ident),*) => {
        $(
            impl<'a> From<$t> for Repr<'a> {
                fn from(value: $t) -> Self {
                    Self {
                        $field: value.into(),
                        ..Self::default()
                    }
                }
            }
        )*
    };
}

impl_from_for_repr!(
    &'a String => unit,
    &'a str => unit,
    String => unit,
    Cow<'a, str> => unit,
    bool => sep
);
3 Likes

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.