rune/runtime/
type_of.rs

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