trait_bounds/lib.rs
1//! This nightly-only library provides useful primitives for defining trait bounds
2//!
3//! [`eq`] and [`ne`] functions allow to check whether two types are equal in a `const` context
4//!
5//! [`type_id`] is similar to [`core::intrinsics::type_id`], but it can be used on [`PointeeSized`](core::marker::PointeeSized) types
6//!
7//! [`Assert<true>`] implements [`IsTrue`]
8//!
9//! [`Assert<false>`] implements [`IsFalse`]
10//!
11//! [`Is<T>`] is implemented for `U` if and only if `U` is equal to `T`
12//!
13//! [`Not<T>`] is implemented for `U` if and only if `U` is not equal to `T`
14//!
15//! The [`Not`] trait can be used to define multiple blanket implementations, which is particularly useful with the [`From<T>`] trait,
16//! as [`From<T> for T`](From<T>#impl-From<T>-for-T) often collides with user-defined blanket impls
17//!
18//! ```
19#![doc = include_str!("../examples/from_many.rs")]
20//! ```
21//! ```
22#![doc = include_str!("../examples/somehow.rs")]
23//! ```
24#![no_std]
25#![expect(internal_features)]
26#![expect(incomplete_features)]
27#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
28#![cfg_attr(feature = "generic_const_args", feature(min_generic_const_args))]
29#![cfg_attr(feature = "generic_const_args", feature(generic_const_args))]
30#![cfg_attr(feature = "generic_const_args", feature(generic_const_items))]
31#![feature(core_intrinsics)]
32#![feature(fundamental)]
33#![feature(rustc_attrs)]
34#![feature(intrinsics)]
35#![rustc_no_implicit_bounds]
36
37use core::{any::TypeId, intrinsics::type_id_eq};
38
39/// Returns a [`TypeId`] of a given type
40///
41/// Unlike [`core::intrinsics::type_id`], this can be used on [`PointeeSized`](core::marker::PointeeSized) types
42#[must_use]
43#[rustc_nounwind]
44#[rustc_intrinsic]
45pub const fn type_id<T>() -> TypeId;
46
47/// Returns `true` if `This` and `Other` types are equal, `false` otherwise
48#[must_use]
49pub const fn eq<This, Other>() -> bool {
50 type_id_eq(type_id::<This>(), type_id::<Other>())
51}
52
53/// Returns `true` if `This` and `Other` types are not equal, `false` otherwise
54#[must_use]
55pub const fn ne<This, Other>() -> bool {
56 !eq::<This, Other>()
57}
58
59// using just #[cfg(feature = "generic_const_args")] type const ... causes an error if generic_const_args isn't enabled, as it's a syntax extension
60#[cfg(feature = "generic_const_args")]
61mod generic_const_args;
62#[cfg(feature = "generic_const_args")]
63pub use generic_const_args::{EQ, NE};
64
65/// Implements [`IsTrue`] if and only if `COND` is `true`,
66/// implements [`IsFalse`] if and only if `COND` is `false`
67pub struct Assert<const COND: bool>;
68
69/// Trait used for [`Assert<bool>`] bounds, implemented by [`Assert<true>`] and not implemented by [`Assert<false>`]
70#[fundamental]
71pub trait IsTrue {}
72impl IsTrue for Assert<true> {}
73
74/// Trait used for [`Assert<bool>`] bounds, implemented by [`Assert<false>`] and not implemented by [`Assert<true>`]
75#[fundamental]
76pub trait IsFalse {}
77impl IsFalse for Assert<false> {}
78
79/// [`Is<T>`] is implemented for `U` if and only if `U` is equal to `T`
80#[fundamental]
81pub trait Is<T> {}
82impl<T> Is<T> for T {}
83
84/// [`Not<T>`] is implemented for `U` if and only if `U` is not equal to `T`
85#[fundamental]
86pub trait Not<T> {}
87cfg_select! {
88 feature = "generic_const_exprs" => {
89 impl<This, Other> Not<Other> for This where Assert<{ ne::<This, Other>() }>: IsTrue {}
90 }
91 feature = "generic_const_args" => {
92 impl<This, Other> Not<Other> for This where Assert<{ NE::<This, Other> }>: IsTrue {}
93 }
94 _ => {
95 compile_error!("either generic_const_exprs or generic_const_args feature must be enabled");
96 }
97}