Skip to content
derive simple constructor functions for Rust structs
Branch: master
Clone or download
Latest commit 15f36e4 Nov 11, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Allow no_std use with Default and PhantomData Nov 11, 2018
testcrate Ignore unrelated field attributes Apr 12, 2018
tests Ignore unrelated field attributes Apr 12, 2018
.gitignore Check the updated Cargo.lock back in Mar 8, 2017
.travis.yml Enable Rust 1.15 on Travis CI May 23, 2018
Cargo.lock Fix Cargo.lock Nov 11, 2018
Cargo.toml Allow no_std use with Default and PhantomData Nov 11, 2018
README.md

README.md

A custom derive implementation for #[derive(new)]

A derive(new) attribute creates a new constructor function for the annotated type. That function takes an argument for each field in the type giving a trivial constructor. This is useful since as your type evolves you can make the constructor non-trivial (and add or remove fields) without changing client code (i.e., without breaking backwards compatibility). It is also the most succinct way to initialise a struct or an enum.

Implementation uses macros 1.1 custom derive (which works in stable Rust from 1.15 onwards).

#[no_std] is fully supported if you switch off the default feature "std".

Examples

Cargo.toml:

[dependencies]
derive-new = "0.5"

Include the macro:

#[macro_use]
extern crate derive_new;

Generating constructor for a simple struct:

#[derive(new)]
struct Bar {
    a: i32,
    b: String,
}

let _ = Bar::new(42, "Hello".to_owned());

Default values can be specified either via #[new(default)] attribute which removes the argument from the constructor and populates the field with Default::default(), or via #[new(value = "..")] which initializes the field with a given expression:

#[derive(new)]
struct Foo {
    x: bool,
    #[new(value = "42")]
    y: i32,
    #[new(default)]
    z: Vec<String>,
}

let _ = Foo::new(true);

Generic types are supported; in particular, PhantomData<T> fields will be not included in the argument list and will be intialized automatically:

use std::marker::PhantomData;

#[derive(new)]
struct Generic<'a, T: Default, P> {
    x: &'a str,
    y: PhantomData<P>,
    #[new(default)]
    z: T,
}

let _ = Generic::<i32, u8>::new("Hello");

For enums, one constructor method is generated for each variant, with the type name being converted to snake case; otherwise, all features supported for structs work for enum variants as well:

#[derive(new)]
struct Enum {
    FirstVariant,
    SecondVariant(bool, #[new(default)] u8),
    ThirdVariant { x: i32, #[new(value = "vec![1]")] y: Vec<u8> }
}

let _ = Enum::new_first_variant();
let _ = Enum::new_second_variant(true);
let _ = Enum::new_third_variant(42);
You can’t perform that action at this time.