Resolving trait implementation conflicts

generics, rust, traits

Solution

The problem here is the (current) compiler does not register that `Complex<T>` does not implement `Float`. Imagine if `Complex` did implement `Float`: either there would have to be some way to decide which `impl` to use, or the overlapping code would have to be outlawed... but what if someone only adds the `impl<T> Float for Complex<T>` in some other crate the compiler doesn't know about?

This last point is key: unlike Haskell, Rust's design allows this code to be perfectly OK without any risk, all because Rust differs in how it handles the last point. If you are in a crate that can see a type `Type` and a trait `Trait`, then you know for 100% sure if `Type` implements `Trait`: Rust doesn't have Haskell's open world assumption, as you can only write `impl Trait for Type` if either `Trait` or `Type` lie in the current crate (compilation unit), that is, you can't have orphan instances, where someone implements `Float` for `Complex<T>` in some distant crate.

RFC 24 (that Chris links to) recognises this, allowing these generic implementations to coexist with more specific ones, as long as the implementations are guaranteed to not overlap.

Problem

I'm trying to write some generic math functions in Rust and I keep running into the following error message: ``` error: conflicting implementations for trait SoAndSo ``` Is it possible to solve the problem? If so, how? For example, I'm trying to write a generic dot product that takes two iterators, zips them and iterates over the pairs to accumulate the products. I want this function also to be able to compute complex-valued dot products. The dot product over complex numbers involves conjugating one side. My first idea was to write a trait `Dot1` for a binary function to replace `Mul` in that it also conjugates the left hand side argument. Here's the complete code: ``` extern crate num; use num::complex::Complex; use num::{Float, Num}; trait Dot1<Rhs, Result> { fn dot1(&self, rhs: Rhs) -> Result; } impl<T: Float> Dot1<T, T> for T { // conjugation for reals is a no-op fn dot1(&self, rhs: T) -> T { *self * rhs } } impl<T: Num + Clone> Dot1<Complex<T>, Complex<T>> for Complex<T> { fn dot1(&self, rhs: Complex<T>) -> Complex<T> { self.conj() * rhs } } fn main() { println!("Hello, world!") } ``` Since a `Complex<T>` is not `Float`, there should be no overlap between the two "generic impls". I didn't expect any problems, but every time I try to provide more than one "generic impl" for a trait, the compiler doesn't like it: ``` error[E0119]: conflicting implementations of trait `Dot1<num::Complex<_>, num::Complex<_>>` for type `num::Complex<_>`: --> src/main.rs:17:1 | 10 | impl<T: Float> Dot1<T, T> for T { | ------------------------------- first implementation here ... 17 | impl<T: Num + Clone> Dot1<Complex<T>, Complex<T>> for Complex<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `num::Complex<_>` | = note: upstream crates may add new impl of trait `num::Float` for type `num::Complex<_>` in future versions ``` How can I write a generic, iterator-based dot product that works for both real and complex numbers? Taking the iterators, zipping them, etc. is not a problem and I was even able to figure out what type parameters to use with which bounds. I don't seem able to "unify" certain data types using traits such as the one from above.

Original source