rune/runtime/type_of.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
use crate::alloc;
use crate::compile::meta;
use crate::Hash;
use super::{AnyTypeInfo, Mut, Ref, TypeInfo};
/// Static type hash for a given type.
///
/// This trait allows you to determine the unique hash of any given type that
/// can be used in Rune through the [`HASH`] associated constant.
///
/// This trait is usually implemented automatically through the [`Any` derive].
///
/// A type hash is unique for types which in Rune are considered the same. This
/// might not be true for types in Rust. For example, `&str` and `String` have
/// the same type hash:
///
/// ```
/// use rune::TypeHash;
///
/// assert_eq!(<&str>::HASH, String::HASH);
/// ```
///
/// [`HASH`]: TypeHash::HASH
/// [`Any` derive]: derive@crate::Any
pub trait TypeHash {
/// The complete type hash of the type including type parameters which
/// uniquely identifiers a given type.
///
/// # Examples
///
/// ```
/// use rune::TypeHash;
///
/// assert_ne!(String::HASH, i64::HASH);
///
/// fn is_a_string<T>() -> bool where T: TypeHash {
/// matches!(T::HASH, String::HASH)
/// }
///
/// assert!(is_a_string::<String>());
/// assert!(!is_a_string::<i64>());
/// ```
const HASH: Hash;
}
/// Blanket implementation for references.
impl<T> TypeHash for &T
where
T: ?Sized + TypeHash,
{
const HASH: Hash = T::HASH;
}
/// Blanket implementation for mutable references.
impl<T> TypeHash for &mut T
where
T: ?Sized + TypeHash,
{
const HASH: Hash = T::HASH;
}
/// Trait used for Rust types for which we can determine the runtime type of.
pub trait TypeOf: TypeHash {
/// Type parameters for the type.
///
/// See [`ParametersBuilder`] for more information.
///
/// [`ParametersBuilder`]: crate::hash::ParametersBuilder
const PARAMETERS: Hash = Hash::EMPTY;
/// Access diagnostical type information for the current type.
///
/// This can be easily converted to a [`TypeInfo`] struct which provides
/// human-readable diagnostics that has a reasonable [`Display`] and
/// [`Debug`] implementation for humans.
///
/// See [`Self::type_info()`].
///
/// [`Debug`]: core::fmt::Debug
/// [`Display`]: core::fmt::Display
const STATIC_TYPE_INFO: AnyTypeInfo;
#[inline]
/// Get type info associated with the current type.
fn type_info() -> TypeInfo {
TypeInfo::from(Self::STATIC_TYPE_INFO)
}
}
/// A type that might or might not have a concrete type.
pub trait MaybeTypeOf {
/// Type information for the given type.
fn maybe_type_of() -> alloc::Result<meta::DocType>;
}
impl<T> MaybeTypeOf for &T
where
T: ?Sized + MaybeTypeOf,
{
#[inline]
fn maybe_type_of() -> alloc::Result<meta::DocType> {
T::maybe_type_of()
}
}
impl<T> MaybeTypeOf for &mut T
where
T: ?Sized + MaybeTypeOf,
{
#[inline]
fn maybe_type_of() -> alloc::Result<meta::DocType> {
T::maybe_type_of()
}
}
impl<T> MaybeTypeOf for Ref<T>
where
T: ?Sized + MaybeTypeOf,
{
#[inline]
fn maybe_type_of() -> alloc::Result<meta::DocType> {
T::maybe_type_of()
}
}
impl<T> MaybeTypeOf for Mut<T>
where
T: ?Sized + MaybeTypeOf,
{
#[inline]
fn maybe_type_of() -> alloc::Result<meta::DocType> {
T::maybe_type_of()
}
}
/// Blanket implementation for references.
impl<T> TypeOf for &T
where
T: ?Sized + TypeOf,
{
const PARAMETERS: Hash = T::PARAMETERS;
const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
}
/// Blanket implementation for mutable references.
impl<T> TypeOf for &mut T
where
T: ?Sized + TypeOf,
{
const PARAMETERS: Hash = T::PARAMETERS;
const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
}
/// Blanket implementation for owned references.
impl<T> TypeHash for Ref<T>
where
T: ?Sized + TypeHash,
{
const HASH: Hash = T::HASH;
}
/// Blanket implementation for owned references.
impl<T> TypeOf for Ref<T>
where
T: ?Sized + TypeOf,
{
const PARAMETERS: Hash = T::PARAMETERS;
const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
}
/// Blanket implementation for owned mutable references.
impl<T> TypeHash for Mut<T>
where
T: ?Sized + TypeHash,
{
const HASH: Hash = T::HASH;
}
/// Blanket implementation for owned mutable references.
impl<T> TypeOf for Mut<T>
where
T: ?Sized + TypeOf,
{
const PARAMETERS: Hash = T::PARAMETERS;
const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
}