#[derive(ConstDefault)]
{
    // Attributes available to this derive:
    #[cdef]
}
Available on crate features derive and const_default only.
Expand description

Derives the ConstDefault trait for structs and enums.

For examples look here

For enums, this requires a #[cdef(default)] attribute on exactly one variant.

Default behavior

By default, this derive macro generates a ConstDefault impl with:

Attributes

Container attributes

Attributes used above the type definition.

#[cdef(crate = foo::bar)](example):
Replaces the path to core_extensions with foo::bar

#[cdef(bound(T: Foo + Bar))](example):
Replaces the default bound (ConstDefault) of the T type parameter with the passed-in bounds.
#[cdef(bound(T: ))] is allowed.

#[cdef(no_bounds)](example):
Removes the ConstDefault bound for all type parameters

#[cdef(field_bound)](example):
Removes the ConstDefault bound for type parameters, replacing them with ConstDefault bounds on all of the field types.

#[cdef(where T: Foo + Bar)](example):
Adds arbitrary bounds to the ConstDefault impl.

#[cdef(debug_print)]:
For diagnostics, causes the derive macro to panic with the code generated by it.

Variant attributes

#[cdef(default)](example):
Uses that variant for the default value. This must be used on exactly one variant.

Field attributes

#[cdef(default = <expression>)](example):
Replaces the default value of the field (ConstDefault::DEFAULT) with <expression>, which must be usable in a const context.

#[cdef(field_bound)](example):
Adds a ConstDefault bound for the field type.

Examples

Basic struct

use core_extensions::ConstDefault;
 
#[derive(Debug, PartialEq, ConstDefault)]
struct Foo<T> {
    bar: T,
    baz: Option<String>,
}
 
const DEF: Foo<[bool; 2]> = Foo::DEFAULT;
assert_eq!(DEF, Foo{bar: [false, false], baz: None});
 
assert_eq!(Foo{bar: "", baz: None}, ConstDefault::DEFAULT);
 

Basic enum

use core_extensions::ConstDefault;
 
#[derive(Debug, PartialEq, ConstDefault)]
enum Foo {
    Bar(u32),
    #[cdef(default)]
    Baz(Option<String>),
}
 
const DEF: Foo = ConstDefault::DEFAULT;
assert_eq!(DEF, Foo::Baz(None));
 
assert_eq!(Foo::DEFAULT, Foo::Baz(None));
 

Crate renaming

This example demonstrates how the core_extensions crate can be renamed, passing the new name to the derive macro.

use cext::ConstDefault;
 
#[derive(Debug, PartialEq, ConstDefault)]
#[cdef(crate = cext)]
struct Foo {
    bar: u32,
    baz: Option<String>,
}
 
assert_eq!(Foo::DEFAULT, Foo{bar: 0, baz: None});

Different default value

This example demonstrates replacing the default value for one field. The assigned expression can be anything, so long as it’s usable in a const context.

use core_extensions::ConstDefault;
 
#[derive(Debug, PartialEq, ConstDefault)]
struct Foo {
    #[cdef(default = power(5))]
    bar: u32,
    baz: Option<String>,
}
 
const fn power(n: u32) -> u32 {
    1 << n
}
 
assert_eq!(Foo::DEFAULT, Foo{bar: 32, baz: None});

No Bounds

This example demonstrates removing the default ConstDefault bound on all type parameters.

use core_extensions::ConstDefault;
 
use std::cmp::Ordering;
use std::marker::PhantomData;
 
#[derive(Debug, PartialEq)]
struct NoDefault<T>(T);
 
 
#[derive(Debug, PartialEq, ConstDefault)]
// removes the default `ConstDefault` bound on all type parameters
#[cdef(no_bounds)]
struct NoBounds<T, U, V: 'static> {
    bar: Option<T>,
    baz: PhantomData<U>,
    qux: &'static [V],
}
 
assert_eq!(
    NoBounds::<Ordering, NoDefault<u32>, NoDefault<String>>::DEFAULT,
    NoBounds{bar: None, baz: PhantomData, qux: &[]}
);

Replaced Bounds

This example demonstrates replacing the default ConstDefault bound on type parameters with other bounds.

use core_extensions::ConstDefault;
 
use std::marker::PhantomData;
 
#[derive(Debug, PartialEq)]
struct NoDefault<T>(T);
 
#[derive(Debug, PartialEq, ConstDefault)]
// replaces the default `ConstDefault` bound on the `T` type parameter with no bounds.
#[cdef(bound(T: ))]
// replaces the default bound on `U` with `Copy + ConstDefault`
#[cdef(bound(U: Copy + ConstDefault))]
struct PartialBounds<T, U> {
    bar: PhantomData<T>,
    baz: U,
}
 
const DEF: PartialBounds<NoDefault<()>, u32> = ConstDefault::DEFAULT;
assert_eq!(DEF, PartialBounds{bar: PhantomData, baz: 0});
 

Field Bounds

This example demonstrates how the default ConstDefault bound on type parameters can be replaced with ConstDefault bounds on field types.

use core_extensions::ConstDefault;

use std::marker::PhantomData;
 
#[derive(Debug, PartialEq, ConstDefault)]
// replaces the default `T: ConstDefault` and `U: ConstDefault` bounds with 
// bounds on the types of the fields:
// `PhantomData<T>: ConstDefault` and `Custom<U>: ConstDefault`
#[cdef(field_bound)]
struct FieldBounds<T, U> {
    bar: PhantomData<T>,
    baz: Custom<U>,
}
 
const DEF: FieldBounds<NoDefault<u8>, i32> = FieldBounds::DEFAULT;
assert_eq!(DEF, FieldBounds{bar: PhantomData, baz: Custom(0)});
 
 
#[derive(Debug, PartialEq, ConstDefault)]
#[cdef(bound(T: ConstDefault + Copy))]
struct Custom<T>(T);
 
#[derive(Debug, PartialEq)]
struct NoDefault<T>(T);

Field Bound

This example demonstrates how the ConstDefault bound can be required for only some field types.

use core_extensions::ConstDefault;

use std::marker::PhantomData;
 
#[derive(Debug, PartialEq, ConstDefault)]
// removes the default `T: ConstDefault` and `U: ConstDefault` bounds
#[cdef(no_bounds)]
struct FieldBound<T, U> {
    bar: PhantomData<T>,
    // Adds a `Custom<U>: ConstDefault` bound 
    #[cdef(field_bound)]
    baz: Custom<U>,
}
 
const DEF: FieldBound<NoDefault<u8>, i32> = FieldBound::DEFAULT;
assert_eq!(DEF, FieldBound{bar: PhantomData, baz: Custom(0)});
 
 
#[derive(Debug, PartialEq, ConstDefault)]
#[cdef(bound(T: ConstDefault + Copy))]
struct Custom<T>(T);
 
#[derive(Debug, PartialEq)]
struct NoDefault<T>(T);

Extra bounds

This example demonstrates how additional bounds can be put in the ConstDefault impl.

use core_extensions::ConstDefault;

#[derive(Debug, PartialEq, ConstDefault)]
// Adds `T: Copy` and `u128: From<T>` bounds to the ConstDefault impl.
#[cdef(where T: Copy, u128: From<T>)]
struct ExtraBounds<T>(T);
 
assert_eq!(ExtraBounds::<u8>::DEFAULT, ExtraBounds(0));
assert_eq!(ExtraBounds::<u32>::DEFAULT, ExtraBounds(0));