error[E0119]: conflicting implementations of trait `SomeTrait`
トレイト実装の指定が既存のものと衝突した。
同じ型と同じトレイトの組合せで、すでに他に実装があると衝突する。
これがもし許されると、どの実装が正しいのか分からなくなってしまう。
マーカートレイトのような空のトレイトについても、例外扱いはされない。つまり、空の実装どうしでも衝突しうる (ソースが短くなるので以降のサンプルでは多用している)。
同じ型と同じトレイトですでに実装があるパターン。
以下では、全く同じトレイトと型ですでに実装がある。
trait MyTrait {}
struct MyType {}
impl MyTrait for MyType {}
impl MyTrait for MyType {}
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`
--> src\lib.rs:5:1
|
4 | impl MyTrait for MyType {}
| ----------------------- first implementation here
5 | impl MyTrait for MyType {}
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
同じトレイトについて、個別の型への実装と、ブランケット実装がある。
そして、個別の型がブランケット実装の範囲に含まれてしまっている。
以下では、MyType は T に含まれている。
trait MyTrait {}
struct MyType {}
impl MyTrait for MyType {}
impl<T> MyTrait for T {}
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`
--> src\sub.rs:5:1
|
4 | impl MyTrait for MyType {}
| ----------------------- first implementation here
5 | impl<T> MyTrait for T {}
| ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
同じトレイトについて、ブランケット実装が複数ある。
そして、両者の範囲が重複してしまっている。
以下では、TraitX と TraitY の両方を実装する型への考慮がない。
trait MyTrait {}
trait TraitX {}
trait TraitY {}
impl<T> MyTrait for T where T: TraitX {}
impl<T> MyTrait for T where T: TraitY {}
error[E0119]: conflicting implementations of trait `MyTrait`
--> src\lib.rs:6:1
|
5 | impl<T> MyTrait for T where T: TraitX {}
| --------------------- first implementation here
6 | impl<T> MyTrait for T where T: TraitY {}
| ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
ジェネリクス型どうしが同じになりうるパターン。
以下では、MyType<i32> と MyType<T> は同じになりうる。
trait MyTrait {}
struct MyType<T>(T);
impl MyTrait for MyType<i32> {}
impl<T> MyTrait for MyType<T> {}
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType<i32>`
--> src\lib.rs:5:1
|
4 | impl MyTrait for MyType<i32> {}
| ---------------------------- first implementation here
5 | impl<T> MyTrait for MyType<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType<i32>`
ジェネリクストレイトどうしが同じになりうるパターン。
以下では、MyTrait<i32> と MyTrait<T> は同じになりうる。
trait MyTrait<T> {}
struct MyType {}
impl MyTrait<i32> for MyType {}
impl<T> MyTrait<T> for MyType {}
error[E0119]: conflicting implementations of trait `MyTrait<i32>` for type `MyType`
--> src\lib.rs:5:1
|
4 | impl MyTrait<i32> for MyType {}
| ---------------------------- first implementation here
5 | impl<T> MyTrait<T> for MyType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
トレイトと型に同じ型パラメタが含まれるパターン。
以下では、MyTrait<i32> と i32 の組は、MyTrait<T> と T の組と同じになりうる。
trait MyTrait<T> {}
impl MyTrait<i32> for i32 {}
impl<T> MyTrait<T> for T {}
error[E0119]: conflicting implementations of trait `MyTrait<i32>` for type `i32`
--> src\lib.rs:4:1
|
3 | impl MyTrait<i32> for i32 {}
| ------------------------- first implementation here
4 | impl<T> MyTrait<T> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
関連型を区別しない問題がある。
以下では、HasType<Type = i32> と HasType<Type = i64> 区別されず衝突にいたる。
trait MyTrait {}
trait HasType { type Type; }
impl<T: HasType<Type = i32>> MyTrait for T {}
impl<T: HasType<Type = i64>> MyTrait for T {}
error[E0119]: conflicting implementations of trait `MyTrait`
--> src\lib.rs:5:1
|
4 | impl<T: HasType<Type = i32>> MyTrait for T {}
| ------------------------------------------ first implementation here
5 | impl<T: HasType<Type = i64>> MyTrait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
作成中のクレートと上流クレートのトレイト実装が衝突するパターン。
これは身に覚えがないぶん、いざ発生すると混乱しやすい。
以下では、core にある From のブランケット実装 (自身への恒等変換) と重複がおきる。
struct MyType {}
impl From<MyType> for MyType {
fn from(value: MyType) -> Self {
value
}
}
error[E0119]: conflicting implementations of trait `From<MyType>` for type `MyType`
--> src\lib.rs:3:1
|
3 | impl From<MyType> for MyType {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
型へのトレイト実装とブランケット実装との将来的な衝突を予防するパターン。
これは型が上流クレート由来で、衝突の有無がその上流クレート次第だと発生する。
以下では、std が将来的に f32 に Eq を実装すると、前のブランケット実装と衝突する (そのような変更は今後とも絶対にないだろうが、あり得そうかどうかでなく、上流クレート次第の状況になるとエラーが発生する)。
trait MyTrait {}
struct MyType<T>(T);
impl<T: Eq> MyTrait for MyType<T> {}
impl<T> MyTrait for MyType<f32> {}
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType<f32>`
--> src\lib.rs:5:1
|
4 | impl<T: Eq> MyTrait for MyType<T> {}
| --------------------------------- first implementation here
5 | impl<T> MyTrait for MyType<f32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType<f32>`
|
= note: upstream crates may add a new impl of trait `std::cmp::Eq` for type `f32` in future versions
作成中のクレートの下流クレートでありうる実装を考慮したパターン。
これは下流クレートがトレイト実装を、作成中のクレートを含む上流クレートが提供するトレイトと型で行う可能性を考慮している (『孤児ルール』の『基本ルール』のみを考えるとこれは不可能に思えるが、『追加ルール』により型パラメタつきのトレイトで可能となる)。
以下では、下流クレートが OurTrait を OurType に実装するかもしれない。
trait MyTrait {}
trait OurTrait<T> {}
struct OurType {}
impl MyTrait for OurType {}
impl<T, U> MyTrait for T where T: OurTrait<U> {}
error[E0119]: conflicting implementations of trait `MyTrait` for type `OurType`
--> src\lib.rs:6:1
|
5 | impl MyTrait for OurType {}
| ------------------------ first implementation here
6 | impl<T, U> MyTrait for T where T: OurTrait<U> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OurType`
|
= note: downstream crates may implement trait `OurTrait<_>` for type `OurType`