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