How to resolve the overlapping of inherent implimentations


#1

The following code runs successfully in stable but has a warning of overlapping_inherent_impls in nightly:

use std::ops::{Neg};

#[derive(Copy, Clone, Debug)]
struct Foo<T> {
    t: T,
}

impl<T: Copy + Neg<Output=T>> Foo<T> {
    fn range(&self) -> (T, T) {
        let t = self.t;
        (-t, t)
    }
}

impl<T: Copy> Foo<(T, T)> {
    fn range(&self) -> (T, T) {
        self.t
    }
}

impl<T: Copy> Foo<[T; 2]> {
    fn range(&self) -> (T, T) {
        let t = self.t;
        (t[0], t[1])
    }
}

fn main() {
    let foo1 = Foo { t: 10 };
    let foo2 = Foo { t: (-10, 10) };
    let foo3 = Foo { t: [-10, 10] };
    println!("foo1: {:?}", foo1.range());
    println!("foo2: {:?}", foo2.range());
    println!("foo3: {:?}", foo3.range());
}

You can test it at http://is.gd/zE6WTy

How can we resolve this kind of overlapping?


#2

The compiler warning links to this thread, which explains in detail why this behavior is being deprecated.
The warning explicitly refers to inherent implementations, i.e. those that aren’t trait-based.
You can work around it by defining a trait

trait Ranged<T> {
    fn range(&self) -> (T, T);
}

and then implementing this trait for your struct Foo<T>:

impl<T: Copy> Ranged<T> for Foot<(T, T)> {...}