I have an enum:
enum Field {
    Str(String),
    Integer(i64),
}
I want to do:
impl From<String> for Field {
    fn from(s: String) -> Field {
        Field::Str(s)
    }
}
impl<I> From<I> for Field where I: Into<i64> + Copy {
    fn from(i: I) -> Field {
        Field::Integer(Into::<i64>::into(i))
    }
}
This code above has an error:
error[E0119]: conflicting implementations of trait
`std::convert::From<std::string::String>` for type `Field`:
--> <anon>:12:5
   |
6  |          impl From<String> for Field {
   |  ________- starting here...
7  | |       fn from(s: String) -> Field {
8  | |         Field::Str(s)
9  | |       }
10 | |     }
   | |_____- ...ending here: first implementation here
11 | 
12 |       impl<I> From<I> for Field where I: Into<i64> + Copy {
   |  _____^ starting here...
13 | |       fn from(i: I) -> Field {
14 | |         Field::Integer(Into::<i64>::into(i))
15 | |       }
16 | |     }
   | |_____^ ...ending here: conflicting implementation for `Field`
String is not an implementor of Into<i64>, so why does error E0119 happen?
TL;DR: where clauses don't count.
The crux of the issue is that the conflict detection is solely pattern based at the moment: it does not account for where clauses.
The problem is 3-fold:
where clauses allow overlap or not is quite complicated,where clause is more specialized than another is quite complicated (upcoming specialization),The first two are purely implementation details, however the latter is a real concern in terms of language design. Imagine that:
Copy bound,impl Into<i64> for &str.And suddenly, there's a conflict where there was none before! You cannot upgrade!
So there's a real design choice here. You have to pick between:
You can't have both.
Note: try typing Rust explain <code> in your search engine of choice, and behold E0119. Although it's not that helpful here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With