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}