Expand description
§ctoption
A compile-time option type for Rust with the discriminant elevated to compile time.
§Add to your project
cargo add ctoption§Usage
§Creating and using CTSome and CTNone
use ctoption::prelude::*;
// enforcing constant evaluation
const _: () = {
let some = CTSome::new(42);
assert!(some.is_some());
assert!(some.into_inner() == 42);
let none = CTNone::<u32>::new();
assert!(!none.is_some());
// at the moment of writing, const drop is unstable
none.forget();
};§Inserting values into a CTNone and extracting them from a CTSome
use ctoption::prelude::*;
// enforcing constant evaluation
const _: () = {
let mut none: CTNone<u32> = CTNone::new();
assert!(!none.is_some());
// What insert does is:
// 1. accepts an owned value
// 2. consumes the CTNone instance
// 3. returns a CTSome instance
let some: CTSome<u32> = none.insert(42);
assert!(some.is_some());
assert!(some.into_inner() == 42);
};§Limitations
§const drop
At the moment of writing, const_destruct feature of Rust is unstable. This means that CTSome and CTNone cannot be dropped in a const context.
However,
CTSomecan be disposed of by callingCTSome::into_inner,CTNonecan be disposed of by callingCTNone::forget.
§.map-like methods
At the moment of writing, methods like std::option::Option::map cannot be implemented for CTSome and CTNone because they require a closure to be passed to them. Closures cannot be evaluated in const contexts. And the attempts to provide a sealed trait with an implementation for a function pointer failed because implementing a trait that would allow using it in a const context is impossible at the time of writing.
§Type narrowing
At the moment of writing, matching on IS_SOME_VAL for CTOption<T, IS_SOME_VAL: bool does not narrow the type to CTSome<T> or CTNone<T>.
However, you can manually narrow the type using the unsafe methods
CTOption::assume_some and CTOption::assume_none:
use ctoption::prelude::*;
const fn add_inner_or_none<const IS_SOME_VAL: bool>(a: u32, b: CTOption<u32, IS_SOME_VAL>) -> u32 {
if b.is_some() {
let some: CTSome<u32> = unsafe { b.assume_some() };
a + some.into_inner()
} else {
let none: CTNone<u32> = unsafe { b.assume_none() };
none.forget();
a
}
}
const _: () = {
let some = CTSome::new(2);
assert!(add_inner_or_none(2, some) == 4);
let none = CTNone::<u32>::new();
assert!(add_inner_or_none(2, none) == 2);
};Additionally, since Rust’s compiler can’t infer after checking IS_SOME_VAL in const context that, for example, CTOption<T, IS_SOME_VAL> is the same as CTSome<T>, you may be in a situation where
- you have
CTSome<T>, - the check in const context inferred that
IS_SOME_VAListrue, - you need to return
CTOption<T, IS_SOME_VAL>
and be confused why returning CTSome<T> doesn’t work.
To resolve this, you can use, CTSome::assume_const_generic_val or CTNone::assume_const_generic_val.
§License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Modules§
Structs§
- CTOption
- A compile-time alternative to
Option. UnlikeOption, this type is guaranteed to have the same size and alignmemt asT.
Constants§
- IS_NONE
- A convenience constant for
false, which is used to indicate that theCTOptioninstance is aCTNone. - IS_SOME
- A convenience constant for
true, which is used to indicate that theCTOptioninstance is aCTSome.
Type Aliases§
- CTNone
- A convenience type alias for
CTOptionwithfalseas the second type parameter. This type alias is inspired by theNonevariant of theOptiontype. - CTSome
- A convenience type alias for
CTOptionwithtrueas the second type parameter. This type alias is inspired by theSomevariant of theOptiontype.