Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I work around the "upstream crates may add a new impl of trait" error?

Tags:

rust

traits

I have created a trait for transforming from some values to a type I need. That conversion is already covered by From/Into for many types, but not everything I want. I thought I could exploit this, but quickly got an error "upstream crates may add a new impl of trait".

(stripped-down example in the playground)

pub trait Cookable {
    fn cook(self) -> (String, Vec<i8>);
}

impl<T: Into<Vec<i8>>> Cookable for T {
    fn cook(self) -> (String, Vec<i8>) {
        (String::from("simple"), self.into())
    }
}

impl Cookable for &str {
    fn cook(self) -> (String, Vec<i8>) {
        (String::from("smelly"), vec![self.len()])
    }
}

That triggers the following error:

error[E0119]: conflicting implementations of trait `Cookable` for type `&str`:
  --> src/lib.rs:11:1
   |
5  | impl<T: Into<Vec<i8>>> Cookable for T {
   | ------------------------------------- first implementation here
...
11 | impl Cookable for &str {
   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&str`
   |
   = note: upstream crates may add a new impl of trait `std::convert::From<&str>` for type `std::vec::Vec<i8>` in future versions

I am worried that the only way to work around this error is to specify individual trait implementations for every one of the types that already has an Into.

like image 840
Mutant Bob Avatar asked Jul 28 '20 14:07

Mutant Bob


1 Answers

It's not a problem you can "work around". It's a limitation imposed by the compiler to prevent future changes to your dependencies from subtly changing the behavior of your code.

For now, you avoid the error by implementing for concrete types instead of using generics and traits. A macro is one way to reduce the amount of keyboard entry you have to do.

In the future, some form of specialization might also be useful to solve this. However, this sits squarely in the middle of the reason that specialization isn't stable. It's possible to use this type of specialization to create unsound Rust using only safe code. A reduced form of specialization is being worked on, but it deliberately eschews the ability to specialize based on a trait and only works for concrete types.

See also:

  • Resolving trait implementation conflicts
  • Conflicting implementations of trait in Rust
  • How can I implement From for both concrete Error types and Box<Error> in Rust?
  • How is there a conflicting implementation of `From` when using a generic type?
  • I implemented a trait for another trait but cannot call methods from both traits
like image 119
Shepmaster Avatar answered Nov 02 '22 01:11

Shepmaster