Expand description

examples

This crate allows you to destructure structs that implement Drop.

If you’ve ever struggled with error E0509 “cannot move out of type T, which implements the Drop trait” then this crate may be for you.

To use this crate, put this in your lib.rs or main.rs for rust < 1.30:

#[macro_use]
extern crate derive_destructure2;

For rust >= 1.30, just import it as a regular item:

use derive_destructure2::{destructure, remove_trait_impls};

Then you have 2 ways to use this crate:

§Option 1: #[derive(destructure)]

If you mark a struct with #[derive(destructure)], then you can destructure it using from your crate

use derive_destructure2::destructure;

#[derive(destructure)]
struct S {
    field_1: u32,
    field_2: i32
}

let val = S {
    field_1: 1,
    field_2: 2,
};
let (field_1, field_2) = val.destructure();

This turns the struct into a tuple of its fields without running the struct’s drop() method. You can then happily move elements out of this tuple.

Note: in Rust, a tuple of 1 element is denoted as (x,), not (x).

destructure is implemented as a private associated function.

§Option 2: #[derive(remove_trait_impls)]

If you mark your struct with #[derive(remove_trait_impls)], then you can do from your crate

use derive_destructure2::remove_trait_impls;

#[derive(remove_trait_impls)]
struct S {
    field_1: u32,
    field_2: i32
}
impl Drop for S {
    fn drop(&mut self) {
        panic!("Dropped!");
    }
}

let val = S {
    field_1: 1,
    field_2: 2,
};
let val = val.remove_trait_impls();

// Dropping val no longer calls `S::drop`.
drop(val);

The result is a struct with the same fields, but it implements no traits (except automatically-implemented traits like Sync and Send). In particular, it doesn’t implement Drop, so you can move fields out of it.

The name of the resulting struct is the original name plus the suffix WithoutTraitImpls.

For example, Foo becomes FooWithoutTraitImpls. But you usually don’t need to write out this name.

#[derive(remove_trait_impls)] works on enums too.

remove_trait_impls is a private associated function.

§Example:

use derive_destructure2::*;

#[derive(destructure, remove_trait_impls)]
struct ImplementsDrop {
    some_str: String,
    some_int: i32
}

impl Drop for ImplementsDrop {
    fn drop(&mut self) {
        panic!("We don't want to drop this");
    }
}

// Using destructure():
let x = ImplementsDrop {
    some_str: "foo".to_owned(),
    some_int: 4
};
let (some_str, some_int) = x.destructure();
// x's drop() method never gets called

// Using remove_trait_impls():
let x = ImplementsDrop {
    some_str: "foo".to_owned(),
    some_int: 4
};
let x = x.remove_trait_impls();
// this x doesn't implement drop,
// so we can move fields out of it
drop(x.some_str);
println!("{}", x.some_int);

Derive Macros§