Function blanket_impls

Source
pub fn blanket_impls()
Expand description

§Overlapping blanket impls

当前 Rust 不支持 trait 为 同一个类型覆盖实现:

    trait Blanket {
        fn blanket(&self) -> &'static str;
    }

    impl Blanket for u8 {
        fn blanket(&self) -> &'static str {
            "impl1"
        }
    }

    // Compilation fails at that point
    impl Blanket for u8 {
        fn blanket(&self) -> &'static str {
            "impl2"
        }
    }

    fn main() {
        // If compilation succeeded, what would be printed?
        println!("{}", 0u8.blanket());
    }

再比如泛型:

    impl <T: ToString> Blanket for T { ... }

    // Compilation fails at that point
    impl <T: Clone> Blanket for T { ...}

以上是 Rust 不允许的。

虽然特化功能也逐渐开始支持,但不足以解决上面这种存在trait实现“竞争”的情况。

一个解决方案是:

    trait Blanket<I> {
        fn blanket(&self) -> &'static str;
    }

    impl Blanket<u8> for u8 {
        fn blanket(&self) -> &'static str {
            "u8"
        }
    }

    impl<T: ToString> Blanket<&ToString> for T {
        fn blanket(&self) -> &'static str {
            "ToString"
        }
    }

    trait CloneBlanket {}

    impl<T: Clone> Blanket<&CloneBlanket> for T {
        fn blanket(&self) -> &'static str {
            "Clone"
        }
    }

    trait TryIntoBlanket<T> {
        type Error;
    }

    impl<T, E, U> Blanket<&TryIntoBlanket<T, Error = E>> for U
    where
        U: TryInto<T, Error = E>,
    {
        fn blanket(&self) -> &'static str {
            "try_into"
        }
    }

    impl<T: ToString> Blanket<&ToString> for T {
        fn blanket(&self) -> &'static str {
            "to_string"
        }
    }

    impl<T: AsRef<U>, U: ?Sized> Blanket<&AsRef<U>> for T {
        fn blanket(&self) -> &'static str {
            "as_ref"
        }
    }

方案参考:https://codesandwich.github.io/overlapping_blanket_impls/