arraysrustcontainerslanguage-lawyerdestructor

Why destruction order of array elements is not from last to first?


Does Rust have any rules regarding calling drop on arrays? Or vectors?

E.g. in C++ desctruction order of array elements is from last to first (opposite to construction order) while in Rust it seems oppostite - however for "single" variables order of destructions is reverse order of construction which seems to be more safe.

See demo

#[derive(Debug)]
struct A(u32);
impl Drop for A {
    fn drop(&mut self) {
        println!("{self:?}");
    }
} 

fn main() {
    {
        let _a1 = A(1);
        let _a2 = A(2);
        let _a3 = A(3);
    }
    println!("---------");
    let av = vec![A(1), A(2), A(3)];
    drop(av);
    println!("---------");
    let aa = [A(1), A(2), A(3)];
    drop(aa);
}


Output:

A(3)
A(2)
A(1)
---------
A(1)
A(2)
A(3)
---------
A(1)
A(2)
A(3)

Solution

  • An array drops elements in the order specified in the reference:

    The destructor of a type T consists of:

    1. If T: Drop, calling <T as std::ops::Drop>::drop
    2. Recursively running the destructor of all of its fields.
      • The fields of a struct are dropped in declaration order.
      • The fields of the active enum variant are dropped in declaration order.
      • The fields of a tuple are dropped in order.
      • The elements of an array or owned slice are dropped from the first element to the last.
      • The variables that a closure captures by move are dropped in an unspecified order.
      • Trait objects run the destructor of the underlying type.
      • Other types don’t result in any further drops.

    A Vec as specified in the first clause (and just like any other type that implements Drop) just calls Vec::drop which does not specify any order (the current implementation just defers to dropping a slice and is likely to continue to behave that way).

    variables order of destructions is reverse order of construction which seems to be more safe.

    A struct declaration does not affect how a struct and it's parts are constructed so that's not a factor in Rust.