Description
In the following scenario, a local trait is default-implemented for a collection of types and once for a specific type.
#![feature([min_]specialization)]
use num::One;
trait Trait1 {
fn f();
}
impl<T: One> Trait1 for T {
default fn f() {}
}
impl Trait1 for u64 {
fn f() {}
}
use std::num::NonZeroU64;
impl Trait1 for NonZeroU64 {
fn f() {}
}
fn main() {
let _: u64 = One::one(); // `One` is implemented for `u64`
}
This gives the error
error[E0119]: conflicting implementations of trait `Trait1` for type `std::num::NonZeroU64`:
--> src/main.rs:19:1
|
9 | impl<T: One> Trait1 for T {
| ------------------------- first implementation here
...
19 | impl Trait1 for NonZeroU64 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::num::NonZeroU64`
|
= note: upstream crates may add a new impl of trait `num::One` for type `std::num::NonZeroU64` in future versions
Without the default
keyword, the error makes sense: there would be a conflicting implementation if num::One
were implemented for NonZeroU64
in the num
crate. We however know that our impl Trait1 for NonZeroU64
implementation will always be more specific than the impl<T: One> Trait1 for T
, so I believe that this should work.
It actually does work for u64
, for which num::One
is implemented. I think that this code should compile independently of whether num
actually holds an implementation of num::One
for the specific type. In this case it does for u64
(for which a specialization compiles) and not for NonZeroU64
(for which a specialization does is rejected).