How to Box a trait that has associated types?

前端 未结 1 1157
滥情空心
滥情空心 2020-12-21 08:05

I\'m very new to Rust so I may have terminology confused.

I want to use the hashes crates to do some hashing and I want to dynamically pick which algorithm (sha256,

相关标签:
1条回答
  • 2020-12-21 08:49

    The message refers to object safety (longer article). The Digest trait has two incompatibilities:

    1. It uses associated types (this can be worked around by explicitly setting all type parameters to values compatible for all Digest objects).
    2. It has a method (fn result(self) -> …) taking self by value. You won't be able to call it, which ruins usability of this trait.

    Once a trait object is created, information about its subtype-specific features such as memory layout or associated types is erased. All calls to the trait object's methods are done via a vtable pointer. This means they all must be compatible, and Rust can't allow you to call any methods that could vary in these aspects.

    A workaround is to create your custom wrapper trait/adapter that is object-compatible. I'm not sure if that's the best implementation, but it does work:

    trait Digest {
        type Assoc;
        fn result(self);
    }
    
    struct Sha;
    
    impl Digest for Sha {
        type Assoc = u8;
        fn result(self) {}
    }
    
    ///////////////////////////////////////////
    
    trait MyWrapper {
        fn result(&mut self); // can't be self/Sized
    }
    
    impl<T: Digest> MyWrapper for Option<T> {
        fn result(&mut self) {
            // Option::take() gives owned from non-owned
            self.take().unwrap().result() 
        }
    }
    
    fn main() {
        let mut digest: Box<MyWrapper> = Box::new(Some(Sha));
        digest.result();
    }
    
    0 讨论(0)
提交回复
热议问题