use crate;
use PhantomData;
////////////////////////////////////////////////////////////////////////////////
/// Marker trait for types that implement the const comparison methods.
///
/// # Implementors
///
/// Types that implement this trait are also expected to implement at least one of
/// these inherent methods:
///
/// ```ignore
/// // use std::cmp::Ordering;
///
/// const fn const_eq(&self, other: &Self) -> bool
///
/// const fn const_cmp(&self, other: &Self) -> Ordering
///
/// ```
///
/// # Coercions
///
/// The [`Kind`](#associatedtype.Kind) associated type
/// is used in the [`IsAConstCmp`] marker type
/// to automatically wrap types in [`CmpWrapper`] if they're from the standard library,
/// otherwise leaving them unwrapped.
///
///
/// # Example
///
/// ### Manual Implementation
///
/// ```
/// use konst::{
/// cmp::{ConstCmp, IsNotStdKind},
/// const_cmp, const_eq, try_equal,
/// };
///
/// use std::cmp::Ordering;
///
///
/// struct MyType {
/// x: &'static str,
/// y: &'static [u16],
/// }
///
/// impl ConstCmp for MyType {
/// type Kind = IsNotStdKind;
/// }
///
/// impl MyType {
/// pub const fn const_eq(&self, other: &Self) -> bool {
/// const_eq!(self.x, other.x) &&
/// const_eq!(self.y, other.y)
/// }
///
/// pub const fn const_cmp(&self, other: &Self) -> Ordering {
/// try_equal!(const_cmp!(self.x, other.x));
/// try_equal!(const_cmp!(self.y, other.y))
/// }
/// }
///
/// const _: () = {
/// let foo = MyType{x: "hello", y: &[3, 5, 8, 13]};
/// let bar = MyType{x: "world", y: &[3, 5, 8, 13]};
///
/// assert!(matches!(const_cmp!(foo, foo), Ordering::Equal));
/// assert!(matches!(const_cmp!(foo, bar), Ordering::Less));
/// assert!(matches!(const_cmp!(bar, foo), Ordering::Greater));
/// assert!(const_eq!(foo, foo));
/// assert!(!const_eq!(foo, bar));
/// };
/// ```
///
///
/// ### `ìmpl_cmp`-based Implementation
///
/// You can use [`impl_cmp`] to implement this trait,
/// as well as define the same methods for
/// multiple implementations with different type arguments.
///
/// ```
/// use konst::{const_cmp, const_eq, impl_cmp, try_equal};
///
/// use std::cmp::Ordering;
///
///
/// struct MyType<'a, T> {
/// x: &'a str,
/// y: &'a [T],
/// }
///
/// impl_cmp!{
/// // The comparison functions are only implemented for these types.
/// impl['a] MyType<'a, bool>;
/// impl['a] MyType<'a, u16>;
/// impl['a] MyType<'a, &'static str>;
///
/// pub const fn const_eq(&self, other: &Self) -> bool {
/// const_eq!(self.x, other.x) &&
/// const_eq!(self.y, other.y)
/// }
///
/// pub const fn const_cmp(&self, other: &Self) -> Ordering {
/// try_equal!(const_cmp!(self.x, other.x));
/// try_equal!(const_cmp!(self.y, other.y))
/// }
/// }
///
/// const _: () = {
/// let foo = MyType{x: "hello", y: &[3, 5, 8, 13]};
/// let bar = MyType{x: "world", y: &[3, 5, 8, 13]};
///
/// assert!(matches!(const_cmp!(foo, foo), Ordering::Equal));
/// assert!(matches!(const_cmp!(foo, bar), Ordering::Less));
/// assert!(matches!(const_cmp!(bar, foo), Ordering::Greater));
/// assert!(const_eq!(foo, foo));
/// assert!(!const_eq!(foo, bar));
/// };
///
/// const _: () = {
/// let foo = MyType{x: "hello", y: &[false]};
/// let bar = MyType{x: "hello", y: &[true]};
///
/// assert!(matches!(const_cmp!(foo, foo), Ordering::Equal));
/// assert!(matches!(const_cmp!(foo, bar), Ordering::Less));
/// assert!(matches!(const_cmp!(bar, foo), Ordering::Greater));
/// assert!(const_eq!(foo, foo));
/// assert!(!const_eq!(foo, bar));
/// };
///
/// ```
///
/// [`CmpWrapper`]: struct.CmpWrapper.html
/// [`impl_cmp`]: ../macro.impl_cmp.html
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// A helper trait of [`ConstCmp`], used for dereferencing.
/// An implementation detail of [`ConstCmpUnref`].
///////////////////////////////////////////////////////////////////////////////
/// Hack used to automatically wrap standard library types inside [`CmpWrapper`],
/// while leaving user defined types unwrapped.
///
/// This can be constructed with he [`NEW` associated constant](#associatedconstant.NEW)
///
/// # Type parameters
///
/// `K` is `<T as ConstCmp>::Kind`
/// The kind of type that `T` is: either [`IsStdKind`] or
/// [`IsNotStdKind`](crate::cmp::IsNotStdKind).
///
/// `T` is `<R as ConstCmpUnref>::This`,
/// the `R` type after removing all layers of references.
///
/// `R`: Is a type that implements [`ConstCmp`]
///
>,
,
,
)>,
);
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////