How does this Vec<T> mechanism work?

The following code compiles if the vector type is Vec but does not compile if it uses Smallvec. What trick is used in Vec to allow dropping elements without causing a borrow error? Is it a language hack?

 pub type V<T> = Vec<T>;

    struct C<T>(V<T>);
    impl<T> C<T> {
        pub fn push(&mut self, bytes: T) {
            self.0.push(bytes);
        }
    }

    let mut a = [Dropable];
    pub struct Dropable;

    impl Drop for Dropable {
        fn drop(&mut self) {
            info!("drop called");
        }
    }

    pub fn process<T>(c: &mut V<T>) {
        c.clear();
    }

    let mut c = C(V::<_>::new());

    c.push(&a);
    process(&mut c.0);
    a[0] = Dropable;

2 Likes

Vec's Drop implementation is using the dropck eyepatch (#[may_dangle]) on T to tell the compiler that it won't inspect any instances of T in Drop::drop, allowing T to potentially dangle. I.e. T can be a reference or contain references to stuff that has already been dropped. You can read more about this here.

11 Likes