#struct #macro-derive #constructor #enums #functions-for-structs

macro no-std derive-new

#[derive(new)] implements simple constructor functions for structs and enums

19 releases

0.7.0 Aug 29, 2024
0.6.0 Nov 7, 2023
0.5.9 Feb 8, 2021
0.5.8 Aug 18, 2019
0.3.0 Nov 19, 2016

#46 in Procedural macros

Download history 144240/week @ 2025-12-18 85258/week @ 2025-12-25 137729/week @ 2026-01-01 204656/week @ 2026-01-08 193556/week @ 2026-01-15 203837/week @ 2026-01-22 208297/week @ 2026-01-29 247348/week @ 2026-02-05 255037/week @ 2026-02-12 310992/week @ 2026-02-19 335866/week @ 2026-02-26 443255/week @ 2026-03-05 365525/week @ 2026-03-12 311082/week @ 2026-03-19 330172/week @ 2026-03-26 292014/week @ 2026-04-02

1,373,686 downloads per month
Used in 1,387 crates (352 directly)

MIT license

24KB
400 lines

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:

  • Rust Edition 2015

    #[macro_use]
    extern crate derive_new;
    
  • Rust Edition 2018

    use derive_new::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);

To make type conversion easier, #[new(into)] attribute changes the parameter type to impl Into<T>, and populates the field with value.into():

#[derive(new)]
struct Foo {
    #[new(into)]
    x: String,
}

let _ = Foo::new("Hello");

For iterators/collections, #[new(into_iter = "T")] attribute changes the parameter type to impl IntoIterator<Item = T>, and populates the field with value.into_iter().collect():

#[derive(new)]
struct Foo {
    #[new(into_iter = "bool")]
    x: Vec<bool>,
}

let _ = Foo::new([true, false]);
let _ = Foo::new(Some(true));

Generic types are supported; in particular, PhantomData<T> fields will be not included in the argument list and will be initialized 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)]
enum 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);

Dependencies

~105–460KB
~11K SLoC