Is it possible to extract same part of two traits into a new one?

What I want to do is like this following

use num::integer::Roots;
use num::traits::real::Real;

pub trait Sqrt {
    fn sqrt(self) -> Self;
}

impl<T: Real> Sqrt for T {
    fn sqrt(self) -> Self {
        T::sqrt(self)
    }
}

impl<T: Roots> Sqrt for T {
    fn sqrt(self) -> Self {
        Roots::sqrt(&self)
    }
}

But compiler complains as this

error[E0119]: conflicting implementations of trait core::Sqrt:
--> src\core\mod.rs:22:1
|
16 | impl<T: Real> Sqrt for T {
| ------------------------ first implementation here
...
22 | impl<T: Roots> Sqrt for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

Unfortunately this is not possible. Although there exist no types currently that implement both Roots and Real, it is entirely possible for a user to create a type that implements both. To reduce code duplication you can add a macro:

macro_rules! derive_sqrt_for_real {
    ($($ty:ty,)*)=> { $(
        impl Sqrt for $ty {
            fn sqrt(self) -> Self {
                Real::sqrt(self)
            }
        }
    )* };
}
derive_sqrt_for_real!(f32, f64);

And you can write similar code to generate the implementations of types that implement Roots.

2 Likes