Can I implement From<&'static str> and From<&str> for the same type?

With this code:

impl From<&'static str> for Name {
    fn from(s: &'static str) -> Self {
        Name::StaticStr(s)
    }
}

impl From<&str> for Name {
    fn from(s: &str) -> Self {
        todo!()
    }
}

Rust compiler complains like this:

error[E0119]: conflicting implementations of trait `std::convert::From<&'static str>` for type `cos::name::Name`:
  --> src/cos/name.rs:33:1
   |
27 | impl From<&'static str> for Name {
   | -------------------------------- first implementation here
...
33 | impl From<&str> for Name {
   | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `cos::name::Name`

Is there a way to inform the compiler to use the first implementation for 'static strs and the other implementation for all non-static strs?

No, this is not possible (it would require a form of specialization, which does not appear to be coming to the language anytime soon).

Instead, I'd suggest having two ordinary constructors, one of which takes &'static str and one of which takes any &str.

2 Likes

No, and not even with specialization -- this is the reason that specialization is not yet stable, because specializing on lifetimes is unsound in the current implementation. (And, because lifetimes are erased, it might not be possible to make a sound version of specializing on lifetimes.)

Perhaps you'd be interested in Cow<'static, str>? Or making your type Name<'a>, where many people would use it as Name<'static>?

(It would really help to have a type definition and not to have a todo!() there, so we could know what you're hoping to accomplish.)

5 Likes

Thanks for your help. It's straightforward to work-around. Just wanted to make sure I wasn't missing something.