Macro core_extensions::quasiconst
source · [−]macro_rules! quasiconst {
(
$(#[$attr:meta])*
$vis:vis const $ident:ident
$( [$($generic_params:tt)*] )?
: $ty: ty
$(where [$($constraints:tt)*] )?
= $value:expr
$(; $($rem:tt)* )?
) => { ... };
(
$(#[$attr:meta])*
$vis:vis const $ident:ident
$($rem:tt)*
) => { ... };
($(;)?) => { ... };
}
const_val
only.Expand description
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 thatConstVal
is imported to writeFoo::VAL
. -
An inherent
NEW
associated constant that constructs the struct.
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()));
Newer syntax
This is the newer syntax that looks closest to what generic constants would look like.
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;
}
quasiconst!{
// Defaulted const parameters require Rust 1.59.0
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
};
}
Older syntax
This is the older (but equally supported) syntax for generic parameters and
where clauses, using []
for both of 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
};
}