6 releases
0.1.5 | Jul 17, 2022 |
---|---|
0.1.4 | Feb 21, 2022 |
#24 in #const-fn
30 downloads per month
Used in 2 crates
(via zst)
68KB
1.5K
SLoC
Function-like macro that "unconsts" trait implementations
unconst_trait_impl::unconst_trait_impl
turns the Nightly syntax for constant trait implementations into analogous non-const syntax that is accepted on stable toolchain.
The list of features taken into account:
In a vaccum, unconst_trait_impl
procedural function-like macro is fairly useless because its call on constant trait implementation yields the same result as writing the non-const implementation in the first place.
However, with cfg_attr
and remove_macro_call
attributes, unconst_trait_impl
macro allows one to conditionally remove the macro call thus providing support for stable toolchain while also providing functionality relying on Nightly features.
Example
#![cfg_attr(feature = "const_trait_impl", feature(const_trait_impl))]
#![cfg_attr(feature = "const_default_impls", feature(const_default_impls))]
#![cfg_attr(feature = "const_fn_trait_bound", feature(const_fn_trait_bound))]
#[cfg(not(all(
feature = "const_trait_impl",
feature = "const_default_impls",
feature = "const_fn_trait_bound"
)))]
use unconst_trait_impl::unconst_trait_impl;
use core::{default::Default, marker::PhantomData};
#[cfg(all(
feature = "const_trait_impl",
feature = "const_default_impls",
feature = "const_fn_trait_bound"
))]
use remove_macro_call::remove_macro_call;
// Since ZST is both Eq and and PartialEq, it has structural match
// https://github.com/rust-lang/rust/issues/63438
#[derive(Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, Copy)]
pub struct ZST<T: ?Sized>(PhantomData<T>);
pub trait TraitName {}
#[cfg_attr(
all(
feature = "const_trait_impl",
feature = "const_default_impls",
feature = "const_fn_trait_bound"
),
remove_macro_call
)]
unconst_trait_impl! {
impl<T: ?Sized> const TraitName for ZST<T> {}
}
// With `cargo build --features const_trait_impl, const_default_impls, const_fn_trait_bound`
// or with `cargo build --all-features, the code below is expanded as is. Otherwise,
// it gets "unconsted" to be supported by stable toolchain.
#[cfg_attr(
all(
feature = "const_trait_impl",
feature = "const_default_impls",
feature = "const_fn_trait_bound"
),
remove_macro_call
)]
unconst_trait_impl! {
impl<T: ~const TraitName + ?Sized> const Default for ZST<T> {
fn default() -> Self {
ZST(Default::default())
}
}
}
Note: In the real code, the example above could be replaced with a simpler version relying on cfg_aliases
crate.
You can learn more about remove_macro_call
here:
Known limitations
Currently, type parameters (like T
in T: ~const TraitName + ?Sized
) get "unconsted" only when
- they belong to the trait implementation, i.e. when they are in
<..>
or in thewhere
clause of the trait implementation; - they belong to the signatures of methods and associated functions;
Other Items in the trait implementation currently don't get "unconsted".
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Dependencies
~1.5MB
~35K SLoC