#![cfg_attr(not(test), no_std)]
#![allow(internal_features)]
#![allow(clippy::type_complexity)]
#![feature(const_trait_impl)]
#![feature(auto_traits)]
#![feature(negative_impls)]
#![feature(try_trait_v2_yeet)]
#![feature(unboxed_closures)]
#![feature(associated_type_defaults)]
#![feature(associated_const_equality)]
#![feature(structural_match)]
#![feature(core_intrinsics)]
#![feature(const_eval_select)]
#![feature(const_deref)]
#![feature(specialization)]
#![feature(generic_const_exprs)]
moddef::moddef!(
pub mod {
ops,
opt_cell for cfg(feature = "opt_cell"),
},
flat(pub) mod {
optional,
maybe,
pure_maybe,
static_maybe,
pure_static_maybe,
not_void
},
);
#[cfg(feature = "opt_cell")]
pub use opt_cell::OptCell;
#[allow(unused)]
const unsafe fn transmute_same_size<T, U>(value: T) -> U
{
assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
unsafe { core::intrinsics::transmute_unchecked::<T, U>(value) }
}
const fn is_same_type<T, U>() -> bool
where
T: ?Sized,
U: ?Sized
{
assert!(<T as private::MaybeSame::<U>>::IS_SAME == <U as private::MaybeSame::<T>>::IS_SAME);
<T as private::MaybeSame<U>>::IS_SAME
}
#[allow(unused)]
const fn assume_same<T, U>(value: T) -> U
{
assert!(is_same_type::<T, U>());
unsafe { core::intrinsics::transmute_unchecked::<T, U>(value) }
}
#[allow(unused)]
const fn assume_same_ref<T, U>(value: &T) -> &U
{
assert!(is_same_type::<T, U>());
unsafe { core::intrinsics::transmute::<&T, &U>(value) }
}
#[allow(unused)]
const fn assume_same_mut<T, U>(value: &mut T) -> &mut U
{
assert!(is_same_type::<T, U>());
unsafe { core::intrinsics::transmute::<&mut T, &mut U>(value) }
}
const fn copy_ref<T>(src: &T) -> <T as Copied>::Output
where
T: Copied,
<T as Copied>::Output: Copy
{
if is_same_type::<T, <T as Copied>::Output>()
{
return *assume_same_ref::<T, <T as Copied>::Output>(src);
}
assert!(is_same_type::<T, &<T as Copied>::Output>() || is_same_type::<T, &mut <T as Copied>::Output>());
unsafe { **core::intrinsics::transmute::<&T, &&<T as Copied>::Output>(src) }
}
fn clone_ref<T>(src: &T) -> <T as Copied>::Output
where
T: Copied,
<T as Copied>::Output: Clone
{
if is_same_type::<T, <T as Copied>::Output>()
{
return assume_same_ref::<T, <T as Copied>::Output>(src).clone();
}
assert!(is_same_type::<T, &<T as Copied>::Output>() || is_same_type::<T, &mut <T as Copied>::Output>());
unsafe { (*core::intrinsics::transmute::<&T, &&<T as Copied>::Output>(src)).clone() }
}
const fn on_unwrap_empty() -> !
{
panic!("called `Maybe::unwrap()` on a `None` value")
}
const fn on_unwrap_empty_msg(msg: &str) -> !
{
panic!("{}", msg)
}
pub trait Same<T>: private::Same<T> {}
impl<T, U> Same<T> for U where U: private::Same<T> {}
pub trait Copied: private::_Copied
{
type Output;
}
impl<T> Copied for T
where
T: private::_Copied
{
type Output = <T as private::_Copied>::Output;
}
mod private
{
pub trait MaybeSame<T>
where
T: ?Sized
{
const IS_SAME: bool;
}
impl<T, U> MaybeSame<U> for T
where
T: ?Sized,
U: ?Sized
{
default const IS_SAME: bool = false;
}
impl<T> MaybeSame<T> for T
where
T: ?Sized
{
const IS_SAME: bool = true;
}
pub trait Same<T> {}
impl<T, U> Same<T> for U where T: MaybeSame<T, IS_SAME = true> {}
pub trait _Copied: Sized
{
type Output;
}
impl<T> _Copied for T
{
default type Output = T;
}
impl<T> _Copied for &T
{
type Output = T;
}
impl<T> _Copied for &mut T
{
type Output = T;
}
use crate::NotVoid;
pub trait Optional {}
impl<T> Optional for Option<T> {}
pub trait PureMaybe<T>
where
T: ?Sized
{
}
impl<T> PureMaybe<T> for Option<T> {}
impl<T> PureMaybe<T> for T where T: ?Sized {}
impl<T> PureMaybe<T> for () where T: NotVoid + ?Sized {}
}
#[cfg(test)]
mod test
{
use static_assertions::assert_type_eq_all;
use crate as option_trait;
use option_trait::*;
assert_type_eq_all!(<&i32 as Copied>::Output, i32);
#[test]
fn it_works()
{
use option_trait::*;
use static_assertions::*;
assert_type_eq_all!(<Option<&i32> as Maybe<&i32>>::Copied, Option<i32>);
assert_type_eq_all!(<&i32 as Maybe<&i32>>::Copied, i32);
assert_type_eq_all!(<() as Maybe<&i32>>::Copied, ());
assert_type_eq_all!(<[&i32; 1] as Maybe<&i32>>::Copied, [i32; 1]);
assert_type_eq_all!(<[&i32; 0] as Maybe<&i32>>::Copied, [i32; 0]);
let maybe = [777];
let referenced = Maybe::<i32>::as_ref(&maybe);
let copy2 = Maybe::<&i32>::copied(&referenced);
assert_eq!(copy2, [777]);
}
#[test]
fn pinned()
{
use option_trait::*;
let maybe = core::pin::pin!(777);
assert!(maybe.is_some());
assert_eq!(**maybe.unwrap_ref(), 777);
let option = maybe.option_pin_mut();
assert!(option.is_some());
assert_eq!(*option.unwrap(), 777);
}
}