Macro core_extensions::quasiconst[][src]

macro_rules! quasiconst {
    (
        $(
            $(#[$attr:meta])*
            $vis:vis const $ident:ident
            $( [$($generic_params:tt)*] )? 
            : $ty: ty
            $(where [$($constraints:tt)*] )?
            = $value:expr
        );*
        $(;)?
    ) => { ... };
}
This is supported on crate feature const_val only.

Declare types that emulate generic constants.

Syntax

For an example using all the syntax, you can look at the All of the syntax section

Generated code

This macro generates:

  • A generic zero-sized struct with the name and generic parameters of the const definition passed to this macro.

  • An impl of the ConstVal trait for the struct, with the value for the constant .

  • An inherent VAL associated constant for the struct, to avoid requiring that ConstVal is imported to write Foo::VAL.

  • An inherent NEW associated constant that constructs the struct.

Version compatibility

This macro can only be used inside of functions since Rust 1.45.0, before that version it can only be used outside of functions.

This is because it uses a dependency-free procedural macro to do some token munging.

Examples

Basic

use core_extensions::{getconst, quasiconst};
 
quasiconst!{ const NONE[T]: Option<T> = None }
 
// `getconst` is the unambiguous way to get the constant
assert_eq!([getconst!(NONE<String>); 4], [None, None, None, None]);

// The `VAL` associated constant is another way to get the constant.
//
// I get worse compiler errors with `::VAL` than with `getconst`
// when the bounds of the generic constant aren't satisfied.
assert_eq!([NONE::<u8>::VAL; 4], [None, None, None, None]);
 

ConstVal

This example shows that you can use the generic constants with the ConstVal trait

use core_extensions::{ConstDefault, ConstVal, quasiconst};

quasiconst!{
   pub const PAIR[T: ConstDefault]: (T, T) = ConstDefault::DEFAULT;
}

fn constant<U: ConstVal>() -> U::Ty {
   U::VAL
}

/// You can pass the type you want `constrained` to return as the first type argument.
fn constrained<T, U: ConstVal<Ty = T>>() -> T {
   U::VAL
}

assert_eq!(constant::<PAIR<[u8; 3]>>(), ([0, 0, 0], [0, 0, 0]));
assert_eq!(constant::<PAIR<bool>>(), (false, false));

// Pair<_> is inferred to be `Pair<u8>`
assert_eq!(constrained::<(u8, u8), PAIR<_>>(), (0, 0));

// Pair<_> is inferred to be `Pair<String>`
assert_eq!(constrained::<(String, String), PAIR<_>>(), (String::new(), String::new()));

All of the syntax

Note: This macro allows const parameters (and doesn’t require enabling the “rust_1_51” feature to use them).

use core_extensions::{ConstDefault, getconst, quasiconst};

assert_eq!(getconst!(REFD<'static>), "");
assert_eq!(getconst!(REFD<'static, str>), "");
assert_eq!(getconst!(REFD<'static, [u8]>), &[]);

assert_eq!(getconst!(CONST_GEN<2>), [1, 3]);
assert_eq!(getconst!(CONST_GEN<4>), [1, 3, 6, 10]);
assert_eq!(getconst!(CONST_GEN<6>), [1, 3, 6, 10, 15, 21]);

quasiconst!{
   /// You can document and use attributes on the generated `REFD` struct.
   pub(crate) const REFD['a: 'a, T: 'a + ?Sized = str]: &'a T
   where[&'a T: ConstDefault]
   = <&'a T>::DEFAULT;
    
   // The macro parses defaulted const parameters, but they're not supported by Rust yet.
   pub const CONST_GEN[const N: usize]: [u128; N] = {
       let mut array = [1u128; N];
       let mut i = 1;
       while i < array.len() {
           array[i] += array[i - 1] + i as u128;
           i += 1;
       }
       array
   };
}