Remix.run Logo
itishappy 2 days ago

That gets us halfway there. It makes unwrapping easy, but you still need to remember to rewrap if you've implemented anything.

    use std::ops::Deref;
    
    trait Test {
        fn test(&self);
    }
    
    #[derive(Debug)]
    struct Wrap<T>(T);
    
    impl<T> Test for Wrap<T> {
        fn test(&self) {
            ()
        }
    }
    
    impl<T> Deref for Wrap<T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }
    
    fn main() {
        let thing1 = Wrap(3_i32);
        let thing2 = Wrap(5_i32);
        let sum = *thing1 + *thing2;
        thing1.test();
        thing2.test();
        sum.test(); // error[E0599]: no method named `test` found for type `i32` in the current scope
    }
Also using newtypes to reimplement methods on the base type is frowned upon. I believe that this is why #[derive(Deref)] isn't included in the standard library. See below (emphasis mine):

> So, as a simple, first-order takeaway: if the wrapper is a trivial marker, then it can implement Deref. If the wrapper's entire purpose is to manage its inner type, without modifying the extant semantics of that type, it should implement Deref. If T behaves differently than Target when Target would compile with that usage, it shouldn't implement Deref.

https://users.rust-lang.org/t/should-you-implement-deref-for...