]>
Commit | Line | Data |
---|---|---|
f2b60f7d | 1 | //! Utilities for dynamic typing or type reflection. |
923072b8 FG |
2 | //! |
3 | //! # `Any` and `TypeId` | |
1a4d82fc JJ |
4 | //! |
5 | //! `Any` itself can be used to get a `TypeId`, and has more features when used | |
e74abb32 XL |
6 | //! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` |
7 | //! and `downcast_ref` methods, to test if the contained value is of a given type, | |
8 | //! and to get a reference to the inner value as a type. As `&mut dyn Any`, there | |
e9174d1e | 9 | //! is also the `downcast_mut` method, for getting a mutable reference to the |
e74abb32 | 10 | //! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to |
9cc50fc6 | 11 | //! convert to a `Box<T>`. See the [`Box`] documentation for the full details. |
1a4d82fc | 12 | //! |
e74abb32 | 13 | //! Note that `&dyn Any` is limited to testing whether a value is of a specified |
1a4d82fc JJ |
14 | //! concrete type, and cannot be used to test whether a type implements a trait. |
15 | //! | |
54a0048b | 16 | //! [`Box`]: ../../std/boxed/struct.Box.html |
9cc50fc6 | 17 | //! |
5869c6ff XL |
18 | //! # Smart pointers and `dyn Any` |
19 | //! | |
20 | //! One piece of behavior to keep in mind when using `Any` as a trait object, | |
21 | //! especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply | |
22 | //! calling `.type_id()` on the value will produce the `TypeId` of the | |
23 | //! *container*, not the underlying trait object. This can be avoided by | |
24 | //! converting the smart pointer into a `&dyn Any` instead, which will return | |
25 | //! the object's `TypeId`. For example: | |
26 | //! | |
27 | //! ``` | |
28 | //! use std::any::{Any, TypeId}; | |
29 | //! | |
30 | //! let boxed: Box<dyn Any> = Box::new(3_i32); | |
31 | //! | |
32 | //! // You're more likely to want this: | |
33 | //! let actual_id = (&*boxed).type_id(); | |
34 | //! // ... than this: | |
35 | //! let boxed_id = boxed.type_id(); | |
36 | //! | |
37 | //! assert_eq!(actual_id, TypeId::of::<i32>()); | |
38 | //! assert_eq!(boxed_id, TypeId::of::<Box<dyn Any>>()); | |
39 | //! ``` | |
40 | //! | |
923072b8 | 41 | //! ## Examples |
1a4d82fc JJ |
42 | //! |
43 | //! Consider a situation where we want to log out a value passed to a function. | |
85aaf69f | 44 | //! We know the value we're working on implements Debug, but we don't know its |
9fa01778 | 45 | //! concrete type. We want to give special treatment to certain types: in this |
1a4d82fc JJ |
46 | //! case printing out the length of String values prior to their value. |
47 | //! We don't know the concrete type of our value at compile time, so we need to | |
48 | //! use runtime reflection instead. | |
49 | //! | |
50 | //! ```rust | |
85aaf69f | 51 | //! use std::fmt::Debug; |
1a4d82fc JJ |
52 | //! use std::any::Any; |
53 | //! | |
85aaf69f SL |
54 | //! // Logger function for any type that implements Debug. |
55 | //! fn log<T: Any + Debug>(value: &T) { | |
a1dfa0c6 | 56 | //! let value_any = value as &dyn Any; |
1a4d82fc | 57 | //! |
9fa01778 | 58 | //! // Try to convert our value to a `String`. If successful, we want to |
9ffffee4 | 59 | //! // output the `String`'s length as well as its value. If not, it's a |
1a4d82fc JJ |
60 | //! // different type: just print it out unadorned. |
61 | //! match value_any.downcast_ref::<String>() { | |
62 | //! Some(as_string) => { | |
63 | //! println!("String ({}): {}", as_string.len(), as_string); | |
64 | //! } | |
65 | //! None => { | |
5e7ed085 | 66 | //! println!("{value:?}"); |
1a4d82fc JJ |
67 | //! } |
68 | //! } | |
69 | //! } | |
70 | //! | |
71 | //! // This function wants to log its parameter out prior to doing work with it. | |
c34b1796 | 72 | //! fn do_work<T: Any + Debug>(value: &T) { |
1a4d82fc JJ |
73 | //! log(value); |
74 | //! // ...do some other work | |
75 | //! } | |
76 | //! | |
77 | //! fn main() { | |
78 | //! let my_string = "Hello World".to_string(); | |
79 | //! do_work(&my_string); | |
80 | //! | |
81 | //! let my_i8: i8 = 100; | |
82 | //! do_work(&my_i8); | |
83 | //! } | |
84 | //! ``` | |
923072b8 FG |
85 | //! |
86 | //! # `Provider` and `Demand` | |
87 | //! | |
88 | //! `Provider` and the associated APIs support generic, type-driven access to data, and a mechanism | |
89 | //! for implementers to provide such data. The key parts of the interface are the `Provider` | |
90 | //! trait for objects which can provide data, and the [`request_value`] and [`request_ref`] | |
91 | //! functions for requesting data from an object which implements `Provider`. Generally, end users | |
92 | //! should not call `request_*` directly, they are helper functions for intermediate implementers | |
93 | //! to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is | |
94 | //! no safety concern here; intermediate implementers can typically support methods rather than | |
95 | //! free functions and use more specific names. | |
96 | //! | |
97 | //! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will | |
98 | //! request data from a trait object by specifying the type of the data. | |
99 | //! | |
100 | //! ## Data flow | |
101 | //! | |
102 | //! * A user requests an object of a specific type, which is delegated to `request_value` or | |
103 | //! `request_ref` | |
104 | //! * `request_*` creates a `Demand` object and passes it to `Provider::provide` | |
105 | //! * The data provider's implementation of `Provider::provide` tries providing values of | |
106 | //! different types using `Demand::provide_*`. If the type matches the type requested by | |
107 | //! the user, the value will be stored in the `Demand` object. | |
108 | //! * `request_*` unpacks the `Demand` object and returns any stored value to the user. | |
109 | //! | |
110 | //! ## Examples | |
111 | //! | |
112 | //! ``` | |
113 | //! # #![feature(provide_any)] | |
114 | //! use std::any::{Provider, Demand, request_ref}; | |
115 | //! | |
116 | //! // Definition of MyTrait, a data provider. | |
117 | //! trait MyTrait: Provider { | |
118 | //! // ... | |
119 | //! } | |
120 | //! | |
121 | //! // Methods on `MyTrait` trait objects. | |
122 | //! impl dyn MyTrait + '_ { | |
123 | //! /// Get a reference to a field of the implementing struct. | |
124 | //! pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> { | |
064997fb | 125 | //! request_ref::<T>(self) |
923072b8 FG |
126 | //! } |
127 | //! } | |
128 | //! | |
129 | //! // Downstream implementation of `MyTrait` and `Provider`. | |
130 | //! # struct SomeConcreteType { some_string: String } | |
131 | //! impl MyTrait for SomeConcreteType { | |
132 | //! // ... | |
133 | //! } | |
134 | //! | |
135 | //! impl Provider for SomeConcreteType { | |
136 | //! fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
137 | //! // Provide a string reference. We could provide multiple values with | |
138 | //! // different types here. | |
139 | //! demand.provide_ref::<String>(&self.some_string); | |
140 | //! } | |
141 | //! } | |
142 | //! | |
143 | //! // Downstream usage of `MyTrait`. | |
144 | //! fn use_my_trait(obj: &dyn MyTrait) { | |
145 | //! // Request a &String from obj. | |
146 | //! let _ = obj.get_context_by_ref::<String>().unwrap(); | |
147 | //! } | |
148 | //! ``` | |
149 | //! | |
150 | //! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then | |
9c376795 | 151 | //! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`. |
1a4d82fc | 152 | |
85aaf69f | 153 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 154 | |
48663c56 | 155 | use crate::fmt; |
fe692bf9 | 156 | use crate::hash; |
48663c56 | 157 | use crate::intrinsics; |
1a4d82fc JJ |
158 | |
159 | /////////////////////////////////////////////////////////////////////////////// | |
160 | // Any trait | |
161 | /////////////////////////////////////////////////////////////////////////////// | |
162 | ||
60c5eb7d | 163 | /// A trait to emulate dynamic typing. |
1a4d82fc | 164 | /// |
3157f602 | 165 | /// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. |
9346a6ac | 166 | /// See the [module-level documentation][mod] for more details. |
c34b1796 | 167 | /// |
3dfed10e | 168 | /// [mod]: crate::any |
dfeec247 XL |
169 | // This trait is not unsafe, though we rely on the specifics of it's sole impl's |
170 | // `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be | |
171 | // a problem, but because the only impl of `Any` is a blanket implementation, no | |
172 | // other code can implement `Any`. | |
173 | // | |
174 | // We could plausibly make this trait unsafe -- it would not cause breakage, | |
175 | // since we control all the implementations -- but we choose not to as that's | |
176 | // both not really necessary and may confuse users about the distinction of | |
177 | // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, | |
178 | // but we would likely want to indicate as such in documentation). | |
85aaf69f | 179 | #[stable(feature = "rust1", since = "1.0.0")] |
136023e0 | 180 | #[cfg_attr(not(test), rustc_diagnostic_item = "Any")] |
9e0c209e | 181 | pub trait Any: 'static { |
9346a6ac | 182 | /// Gets the `TypeId` of `self`. |
5bcae85e SL |
183 | /// |
184 | /// # Examples | |
185 | /// | |
186 | /// ``` | |
5bcae85e SL |
187 | /// use std::any::{Any, TypeId}; |
188 | /// | |
a1dfa0c6 | 189 | /// fn is_string(s: &dyn Any) -> bool { |
9fa01778 | 190 | /// TypeId::of::<String>() == s.type_id() |
5bcae85e SL |
191 | /// } |
192 | /// | |
e74abb32 XL |
193 | /// assert_eq!(is_string(&0), false); |
194 | /// assert_eq!(is_string(&"cookie monster".to_string()), true); | |
5bcae85e | 195 | /// ``` |
9fa01778 XL |
196 | #[stable(feature = "get_type_id", since = "1.34.0")] |
197 | fn type_id(&self) -> TypeId; | |
1a4d82fc JJ |
198 | } |
199 | ||
92a42be0 | 200 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
201 | impl<T: 'static + ?Sized> Any for T { |
202 | fn type_id(&self) -> TypeId { | |
203 | TypeId::of::<T>() | |
204 | } | |
1a4d82fc JJ |
205 | } |
206 | ||
207 | /////////////////////////////////////////////////////////////////////////////// | |
208 | // Extension methods for Any trait objects. | |
1a4d82fc JJ |
209 | /////////////////////////////////////////////////////////////////////////////// |
210 | ||
c34b1796 | 211 | #[stable(feature = "rust1", since = "1.0.0")] |
8faf50e0 | 212 | impl fmt::Debug for dyn Any { |
48663c56 | 213 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 214 | f.debug_struct("Any").finish_non_exhaustive() |
c34b1796 AL |
215 | } |
216 | } | |
217 | ||
0731742a | 218 | // Ensure that the result of e.g., joining a thread can be printed and |
9346a6ac AL |
219 | // hence used with `unwrap`. May eventually no longer be needed if |
220 | // dispatch works with upcasting. | |
221 | #[stable(feature = "rust1", since = "1.0.0")] | |
8faf50e0 | 222 | impl fmt::Debug for dyn Any + Send { |
48663c56 | 223 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 224 | f.debug_struct("Any").finish_non_exhaustive() |
9346a6ac AL |
225 | } |
226 | } | |
227 | ||
94b46f34 | 228 | #[stable(feature = "any_send_sync_methods", since = "1.28.0")] |
8faf50e0 | 229 | impl fmt::Debug for dyn Any + Send + Sync { |
48663c56 | 230 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 231 | f.debug_struct("Any").finish_non_exhaustive() |
94b46f34 XL |
232 | } |
233 | } | |
234 | ||
8faf50e0 | 235 | impl dyn Any { |
a2a8927a | 236 | /// Returns `true` if the inner type is the same as `T`. |
5bcae85e SL |
237 | /// |
238 | /// # Examples | |
239 | /// | |
240 | /// ``` | |
241 | /// use std::any::Any; | |
242 | /// | |
a1dfa0c6 | 243 | /// fn is_string(s: &dyn Any) { |
5bcae85e SL |
244 | /// if s.is::<String>() { |
245 | /// println!("It's a string!"); | |
246 | /// } else { | |
247 | /// println!("Not a string..."); | |
248 | /// } | |
249 | /// } | |
250 | /// | |
e74abb32 XL |
251 | /// is_string(&0); |
252 | /// is_string(&"cookie monster".to_string()); | |
5bcae85e | 253 | /// ``` |
85aaf69f | 254 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 255 | #[inline] |
c34b1796 | 256 | pub fn is<T: Any>(&self) -> bool { |
e1599b0c | 257 | // Get `TypeId` of the type this function is instantiated with. |
1a4d82fc JJ |
258 | let t = TypeId::of::<T>(); |
259 | ||
ba9703b0 | 260 | // Get `TypeId` of the type in the trait object (`self`). |
9fa01778 | 261 | let concrete = self.type_id(); |
1a4d82fc | 262 | |
e1599b0c | 263 | // Compare both `TypeId`s on equality. |
9fa01778 | 264 | t == concrete |
1a4d82fc JJ |
265 | } |
266 | ||
a2a8927a | 267 | /// Returns some reference to the inner value if it is of type `T`, or |
1a4d82fc | 268 | /// `None` if it isn't. |
5bcae85e SL |
269 | /// |
270 | /// # Examples | |
271 | /// | |
272 | /// ``` | |
273 | /// use std::any::Any; | |
274 | /// | |
a1dfa0c6 | 275 | /// fn print_if_string(s: &dyn Any) { |
5bcae85e SL |
276 | /// if let Some(string) = s.downcast_ref::<String>() { |
277 | /// println!("It's a string({}): '{}'", string.len(), string); | |
278 | /// } else { | |
279 | /// println!("Not a string..."); | |
280 | /// } | |
281 | /// } | |
282 | /// | |
e74abb32 XL |
283 | /// print_if_string(&0); |
284 | /// print_if_string(&"cookie monster".to_string()); | |
5bcae85e | 285 | /// ``` |
85aaf69f | 286 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 287 | #[inline] |
c34b1796 | 288 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { |
1a4d82fc | 289 | if self.is::<T>() { |
74b04a01 XL |
290 | // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
291 | // that check for memory safety because we have implemented Any for all types; no other | |
292 | // impls can exist as they would conflict with our impl. | |
a2a8927a | 293 | unsafe { Some(self.downcast_ref_unchecked()) } |
1a4d82fc JJ |
294 | } else { |
295 | None | |
296 | } | |
297 | } | |
298 | ||
a2a8927a | 299 | /// Returns some mutable reference to the inner value if it is of type `T`, or |
1a4d82fc | 300 | /// `None` if it isn't. |
5bcae85e SL |
301 | /// |
302 | /// # Examples | |
303 | /// | |
304 | /// ``` | |
305 | /// use std::any::Any; | |
306 | /// | |
a1dfa0c6 | 307 | /// fn modify_if_u32(s: &mut dyn Any) { |
5bcae85e SL |
308 | /// if let Some(num) = s.downcast_mut::<u32>() { |
309 | /// *num = 42; | |
310 | /// } | |
311 | /// } | |
312 | /// | |
e74abb32 XL |
313 | /// let mut x = 10u32; |
314 | /// let mut s = "starlord".to_string(); | |
5bcae85e | 315 | /// |
e74abb32 XL |
316 | /// modify_if_u32(&mut x); |
317 | /// modify_if_u32(&mut s); | |
5bcae85e | 318 | /// |
e74abb32 XL |
319 | /// assert_eq!(x, 42); |
320 | /// assert_eq!(&s, "starlord"); | |
5bcae85e | 321 | /// ``` |
85aaf69f | 322 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 323 | #[inline] |
c34b1796 | 324 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { |
1a4d82fc | 325 | if self.is::<T>() { |
74b04a01 XL |
326 | // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
327 | // that check for memory safety because we have implemented Any for all types; no other | |
328 | // impls can exist as they would conflict with our impl. | |
a2a8927a | 329 | unsafe { Some(self.downcast_mut_unchecked()) } |
1a4d82fc JJ |
330 | } else { |
331 | None | |
332 | } | |
333 | } | |
a2a8927a XL |
334 | |
335 | /// Returns a reference to the inner value as type `dyn T`. | |
336 | /// | |
337 | /// # Examples | |
338 | /// | |
339 | /// ``` | |
340 | /// #![feature(downcast_unchecked)] | |
341 | /// | |
342 | /// use std::any::Any; | |
343 | /// | |
344 | /// let x: Box<dyn Any> = Box::new(1_usize); | |
345 | /// | |
346 | /// unsafe { | |
347 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); | |
348 | /// } | |
349 | /// ``` | |
350 | /// | |
351 | /// # Safety | |
352 | /// | |
353 | /// The contained value must be of type `T`. Calling this method | |
354 | /// with the incorrect type is *undefined behavior*. | |
355 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
356 | #[inline] | |
357 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { | |
358 | debug_assert!(self.is::<T>()); | |
359 | // SAFETY: caller guarantees that T is the correct type | |
360 | unsafe { &*(self as *const dyn Any as *const T) } | |
361 | } | |
362 | ||
363 | /// Returns a mutable reference to the inner value as type `dyn T`. | |
364 | /// | |
365 | /// # Examples | |
366 | /// | |
367 | /// ``` | |
368 | /// #![feature(downcast_unchecked)] | |
369 | /// | |
370 | /// use std::any::Any; | |
371 | /// | |
372 | /// let mut x: Box<dyn Any> = Box::new(1_usize); | |
373 | /// | |
374 | /// unsafe { | |
375 | /// *x.downcast_mut_unchecked::<usize>() += 1; | |
376 | /// } | |
377 | /// | |
378 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); | |
379 | /// ``` | |
380 | /// | |
381 | /// # Safety | |
382 | /// | |
383 | /// The contained value must be of type `T`. Calling this method | |
384 | /// with the incorrect type is *undefined behavior*. | |
385 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
386 | #[inline] | |
387 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { | |
388 | debug_assert!(self.is::<T>()); | |
389 | // SAFETY: caller guarantees that T is the correct type | |
390 | unsafe { &mut *(self as *mut dyn Any as *mut T) } | |
391 | } | |
1a4d82fc | 392 | } |
85aaf69f | 393 | |
dfeec247 | 394 | impl dyn Any + Send { |
a2a8927a | 395 | /// Forwards to the method defined on the type `dyn Any`. |
5bcae85e SL |
396 | /// |
397 | /// # Examples | |
398 | /// | |
399 | /// ``` | |
400 | /// use std::any::Any; | |
401 | /// | |
a1dfa0c6 | 402 | /// fn is_string(s: &(dyn Any + Send)) { |
5bcae85e SL |
403 | /// if s.is::<String>() { |
404 | /// println!("It's a string!"); | |
405 | /// } else { | |
406 | /// println!("Not a string..."); | |
407 | /// } | |
408 | /// } | |
409 | /// | |
e74abb32 XL |
410 | /// is_string(&0); |
411 | /// is_string(&"cookie monster".to_string()); | |
5bcae85e | 412 | /// ``` |
c34b1796 AL |
413 | #[stable(feature = "rust1", since = "1.0.0")] |
414 | #[inline] | |
415 | pub fn is<T: Any>(&self) -> bool { | |
6a06907d | 416 | <dyn Any>::is::<T>(self) |
c34b1796 AL |
417 | } |
418 | ||
a2a8927a | 419 | /// Forwards to the method defined on the type `dyn Any`. |
5bcae85e SL |
420 | /// |
421 | /// # Examples | |
422 | /// | |
423 | /// ``` | |
424 | /// use std::any::Any; | |
425 | /// | |
a1dfa0c6 | 426 | /// fn print_if_string(s: &(dyn Any + Send)) { |
5bcae85e SL |
427 | /// if let Some(string) = s.downcast_ref::<String>() { |
428 | /// println!("It's a string({}): '{}'", string.len(), string); | |
429 | /// } else { | |
430 | /// println!("Not a string..."); | |
431 | /// } | |
432 | /// } | |
433 | /// | |
e74abb32 XL |
434 | /// print_if_string(&0); |
435 | /// print_if_string(&"cookie monster".to_string()); | |
5bcae85e | 436 | /// ``` |
c34b1796 AL |
437 | #[stable(feature = "rust1", since = "1.0.0")] |
438 | #[inline] | |
439 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { | |
6a06907d | 440 | <dyn Any>::downcast_ref::<T>(self) |
c34b1796 AL |
441 | } |
442 | ||
a2a8927a | 443 | /// Forwards to the method defined on the type `dyn Any`. |
5bcae85e SL |
444 | /// |
445 | /// # Examples | |
446 | /// | |
447 | /// ``` | |
448 | /// use std::any::Any; | |
449 | /// | |
a1dfa0c6 | 450 | /// fn modify_if_u32(s: &mut (dyn Any + Send)) { |
5bcae85e SL |
451 | /// if let Some(num) = s.downcast_mut::<u32>() { |
452 | /// *num = 42; | |
453 | /// } | |
454 | /// } | |
455 | /// | |
e74abb32 XL |
456 | /// let mut x = 10u32; |
457 | /// let mut s = "starlord".to_string(); | |
5bcae85e | 458 | /// |
e74abb32 XL |
459 | /// modify_if_u32(&mut x); |
460 | /// modify_if_u32(&mut s); | |
5bcae85e | 461 | /// |
e74abb32 XL |
462 | /// assert_eq!(x, 42); |
463 | /// assert_eq!(&s, "starlord"); | |
5bcae85e | 464 | /// ``` |
c34b1796 AL |
465 | #[stable(feature = "rust1", since = "1.0.0")] |
466 | #[inline] | |
467 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { | |
6a06907d | 468 | <dyn Any>::downcast_mut::<T>(self) |
c34b1796 | 469 | } |
a2a8927a XL |
470 | |
471 | /// Forwards to the method defined on the type `dyn Any`. | |
472 | /// | |
473 | /// # Examples | |
474 | /// | |
475 | /// ``` | |
476 | /// #![feature(downcast_unchecked)] | |
477 | /// | |
478 | /// use std::any::Any; | |
479 | /// | |
480 | /// let x: Box<dyn Any> = Box::new(1_usize); | |
481 | /// | |
482 | /// unsafe { | |
483 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); | |
484 | /// } | |
485 | /// ``` | |
486 | /// | |
487 | /// # Safety | |
488 | /// | |
489 | /// Same as the method on the type `dyn Any`. | |
490 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
491 | #[inline] | |
492 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { | |
493 | // SAFETY: guaranteed by caller | |
494 | unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) } | |
495 | } | |
496 | ||
497 | /// Forwards to the method defined on the type `dyn Any`. | |
498 | /// | |
499 | /// # Examples | |
500 | /// | |
501 | /// ``` | |
502 | /// #![feature(downcast_unchecked)] | |
503 | /// | |
504 | /// use std::any::Any; | |
505 | /// | |
506 | /// let mut x: Box<dyn Any> = Box::new(1_usize); | |
507 | /// | |
508 | /// unsafe { | |
509 | /// *x.downcast_mut_unchecked::<usize>() += 1; | |
510 | /// } | |
511 | /// | |
512 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); | |
513 | /// ``` | |
514 | /// | |
515 | /// # Safety | |
516 | /// | |
517 | /// Same as the method on the type `dyn Any`. | |
518 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
519 | #[inline] | |
520 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { | |
521 | // SAFETY: guaranteed by caller | |
522 | unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) } | |
523 | } | |
c34b1796 AL |
524 | } |
525 | ||
dfeec247 | 526 | impl dyn Any + Send + Sync { |
94b46f34 XL |
527 | /// Forwards to the method defined on the type `Any`. |
528 | /// | |
529 | /// # Examples | |
530 | /// | |
531 | /// ``` | |
532 | /// use std::any::Any; | |
533 | /// | |
a1dfa0c6 | 534 | /// fn is_string(s: &(dyn Any + Send + Sync)) { |
94b46f34 XL |
535 | /// if s.is::<String>() { |
536 | /// println!("It's a string!"); | |
537 | /// } else { | |
538 | /// println!("Not a string..."); | |
539 | /// } | |
540 | /// } | |
541 | /// | |
e74abb32 XL |
542 | /// is_string(&0); |
543 | /// is_string(&"cookie monster".to_string()); | |
94b46f34 XL |
544 | /// ``` |
545 | #[stable(feature = "any_send_sync_methods", since = "1.28.0")] | |
546 | #[inline] | |
547 | pub fn is<T: Any>(&self) -> bool { | |
6a06907d | 548 | <dyn Any>::is::<T>(self) |
94b46f34 XL |
549 | } |
550 | ||
551 | /// Forwards to the method defined on the type `Any`. | |
552 | /// | |
553 | /// # Examples | |
554 | /// | |
555 | /// ``` | |
556 | /// use std::any::Any; | |
557 | /// | |
a1dfa0c6 | 558 | /// fn print_if_string(s: &(dyn Any + Send + Sync)) { |
94b46f34 XL |
559 | /// if let Some(string) = s.downcast_ref::<String>() { |
560 | /// println!("It's a string({}): '{}'", string.len(), string); | |
561 | /// } else { | |
562 | /// println!("Not a string..."); | |
563 | /// } | |
564 | /// } | |
565 | /// | |
e74abb32 XL |
566 | /// print_if_string(&0); |
567 | /// print_if_string(&"cookie monster".to_string()); | |
94b46f34 XL |
568 | /// ``` |
569 | #[stable(feature = "any_send_sync_methods", since = "1.28.0")] | |
570 | #[inline] | |
571 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { | |
6a06907d | 572 | <dyn Any>::downcast_ref::<T>(self) |
94b46f34 XL |
573 | } |
574 | ||
575 | /// Forwards to the method defined on the type `Any`. | |
576 | /// | |
577 | /// # Examples | |
578 | /// | |
579 | /// ``` | |
580 | /// use std::any::Any; | |
581 | /// | |
a1dfa0c6 | 582 | /// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) { |
94b46f34 XL |
583 | /// if let Some(num) = s.downcast_mut::<u32>() { |
584 | /// *num = 42; | |
585 | /// } | |
586 | /// } | |
587 | /// | |
e74abb32 XL |
588 | /// let mut x = 10u32; |
589 | /// let mut s = "starlord".to_string(); | |
94b46f34 | 590 | /// |
e74abb32 XL |
591 | /// modify_if_u32(&mut x); |
592 | /// modify_if_u32(&mut s); | |
94b46f34 | 593 | /// |
e74abb32 XL |
594 | /// assert_eq!(x, 42); |
595 | /// assert_eq!(&s, "starlord"); | |
94b46f34 XL |
596 | /// ``` |
597 | #[stable(feature = "any_send_sync_methods", since = "1.28.0")] | |
598 | #[inline] | |
599 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { | |
6a06907d | 600 | <dyn Any>::downcast_mut::<T>(self) |
94b46f34 | 601 | } |
a2a8927a XL |
602 | |
603 | /// Forwards to the method defined on the type `Any`. | |
604 | /// | |
605 | /// # Examples | |
606 | /// | |
607 | /// ``` | |
608 | /// #![feature(downcast_unchecked)] | |
609 | /// | |
610 | /// use std::any::Any; | |
611 | /// | |
612 | /// let x: Box<dyn Any> = Box::new(1_usize); | |
613 | /// | |
614 | /// unsafe { | |
615 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); | |
616 | /// } | |
617 | /// ``` | |
618 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
619 | #[inline] | |
620 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { | |
621 | // SAFETY: guaranteed by caller | |
622 | unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) } | |
623 | } | |
624 | ||
625 | /// Forwards to the method defined on the type `Any`. | |
626 | /// | |
627 | /// # Examples | |
628 | /// | |
629 | /// ``` | |
630 | /// #![feature(downcast_unchecked)] | |
631 | /// | |
632 | /// use std::any::Any; | |
633 | /// | |
634 | /// let mut x: Box<dyn Any> = Box::new(1_usize); | |
635 | /// | |
636 | /// unsafe { | |
637 | /// *x.downcast_mut_unchecked::<usize>() += 1; | |
638 | /// } | |
639 | /// | |
640 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); | |
641 | /// ``` | |
642 | #[unstable(feature = "downcast_unchecked", issue = "90850")] | |
643 | #[inline] | |
644 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { | |
645 | // SAFETY: guaranteed by caller | |
646 | unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) } | |
647 | } | |
94b46f34 | 648 | } |
c34b1796 | 649 | |
85aaf69f SL |
650 | /////////////////////////////////////////////////////////////////////////////// |
651 | // TypeID and its methods | |
652 | /////////////////////////////////////////////////////////////////////////////// | |
653 | ||
654 | /// A `TypeId` represents a globally unique identifier for a type. | |
655 | /// | |
656 | /// Each `TypeId` is an opaque object which does not allow inspection of what's | |
657 | /// inside but does allow basic operations such as cloning, comparison, | |
658 | /// printing, and showing. | |
659 | /// | |
660 | /// A `TypeId` is currently only available for types which ascribe to `'static`, | |
661 | /// but this limitation may be removed in the future. | |
8bb4bdeb XL |
662 | /// |
663 | /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth | |
664 | /// noting that the hashes and ordering will vary between Rust releases. Beware | |
8faf50e0 | 665 | /// of relying on them inside of your code! |
fe692bf9 | 666 | #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] |
85aaf69f SL |
667 | #[stable(feature = "rust1", since = "1.0.0")] |
668 | pub struct TypeId { | |
fe692bf9 | 669 | t: u128, |
85aaf69f SL |
670 | } |
671 | ||
49aad941 FG |
672 | #[stable(feature = "rust1", since = "1.0.0")] |
673 | impl PartialEq for TypeId { | |
674 | #[inline] | |
675 | fn eq(&self, other: &Self) -> bool { | |
676 | self.t == other.t | |
677 | } | |
678 | } | |
679 | ||
85aaf69f | 680 | impl TypeId { |
2c00a5a8 XL |
681 | /// Returns the `TypeId` of the type this generic function has been |
682 | /// instantiated with. | |
683 | /// | |
684 | /// # Examples | |
685 | /// | |
686 | /// ``` | |
687 | /// use std::any::{Any, TypeId}; | |
688 | /// | |
689 | /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool { | |
690 | /// TypeId::of::<String>() == TypeId::of::<T>() | |
691 | /// } | |
692 | /// | |
e74abb32 XL |
693 | /// assert_eq!(is_string(&0), false); |
694 | /// assert_eq!(is_string(&"cookie monster".to_string()), true); | |
2c00a5a8 | 695 | /// ``` |
3c0e092e | 696 | #[must_use] |
2c00a5a8 | 697 | #[stable(feature = "rust1", since = "1.0.0")] |
6c58768f | 698 | #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] |
2c00a5a8 | 699 | pub const fn of<T: ?Sized + 'static>() -> TypeId { |
fe692bf9 FG |
700 | #[cfg(bootstrap)] |
701 | let t = intrinsics::type_id::<T>() as u128; | |
702 | #[cfg(not(bootstrap))] | |
703 | let t: u128 = intrinsics::type_id::<T>(); | |
704 | TypeId { t } | |
705 | } | |
706 | } | |
707 | ||
708 | #[stable(feature = "rust1", since = "1.0.0")] | |
709 | impl hash::Hash for TypeId { | |
710 | #[inline] | |
711 | fn hash<H: hash::Hasher>(&self, state: &mut H) { | |
712 | // We only hash the lower 64 bits of our (128 bit) internal numeric ID, | |
713 | // because: | |
714 | // - The hashing algorithm which backs `TypeId` is expected to be | |
715 | // unbiased and high quality, meaning further mixing would be somewhat | |
716 | // redundant compared to choosing (the lower) 64 bits arbitrarily. | |
717 | // - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd | |
718 | // get from hashing the full value would probably not be useful | |
719 | // (especially given the previous point about the lower 64 bits being | |
720 | // high quality on their own). | |
721 | // - It is correct to do so -- only hashing a subset of `self` is still | |
722 | // with an `Eq` implementation that considers the entire value, as | |
723 | // ours does. | |
724 | (self.t as u64).hash(state); | |
2c00a5a8 | 725 | } |
85aaf69f | 726 | } |
416331ca XL |
727 | |
728 | /// Returns the name of a type as a string slice. | |
729 | /// | |
730 | /// # Note | |
731 | /// | |
732 | /// This is intended for diagnostic use. The exact contents and format of the | |
f9f354fc XL |
733 | /// string returned are not specified, other than being a best-effort |
734 | /// description of the type. For example, amongst the strings | |
735 | /// that `type_name::<Option<String>>()` might return are `"Option<String>"` and | |
736 | /// `"std::option::Option<std::string::String>"`. | |
416331ca | 737 | /// |
f9f354fc XL |
738 | /// The returned string must not be considered to be a unique identifier of a |
739 | /// type as multiple types may map to the same type name. Similarly, there is no | |
740 | /// guarantee that all parts of a type will appear in the returned string: for | |
741 | /// example, lifetime specifiers are currently not included. In addition, the | |
742 | /// output may change between versions of the compiler. | |
416331ca XL |
743 | /// |
744 | /// The current implementation uses the same infrastructure as compiler | |
745 | /// diagnostics and debuginfo, but this is not guaranteed. | |
e74abb32 | 746 | /// |
60c5eb7d | 747 | /// # Examples |
e74abb32 XL |
748 | /// |
749 | /// ```rust | |
750 | /// assert_eq!( | |
751 | /// std::any::type_name::<Option<String>>(), | |
752 | /// "core::option::Option<alloc::string::String>", | |
753 | /// ); | |
754 | /// ``` | |
3c0e092e | 755 | #[must_use] |
416331ca | 756 | #[stable(feature = "type_name", since = "1.38.0")] |
dfeec247 | 757 | #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] |
416331ca | 758 | pub const fn type_name<T: ?Sized>() -> &'static str { |
416331ca XL |
759 | intrinsics::type_name::<T>() |
760 | } | |
60c5eb7d XL |
761 | |
762 | /// Returns the name of the type of the pointed-to value as a string slice. | |
763 | /// This is the same as `type_name::<T>()`, but can be used where the type of a | |
764 | /// variable is not easily available. | |
765 | /// | |
766 | /// # Note | |
767 | /// | |
768 | /// This is intended for diagnostic use. The exact contents and format of the | |
769 | /// string are not specified, other than being a best-effort description of the | |
dfeec247 | 770 | /// type. For example, `type_name_of_val::<Option<String>>(None)` could return |
60c5eb7d XL |
771 | /// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not |
772 | /// `"foobar"`. In addition, the output may change between versions of the | |
773 | /// compiler. | |
774 | /// | |
dfeec247 XL |
775 | /// This function does not resolve trait objects, |
776 | /// meaning that `type_name_of_val(&7u32 as &dyn Debug)` | |
777 | /// may return `"dyn Debug"`, but not `"u32"`. | |
778 | /// | |
60c5eb7d XL |
779 | /// The type name should not be considered a unique identifier of a type; |
780 | /// multiple types may share the same type name. | |
781 | /// | |
782 | /// The current implementation uses the same infrastructure as compiler | |
783 | /// diagnostics and debuginfo, but this is not guaranteed. | |
784 | /// | |
785 | /// # Examples | |
786 | /// | |
787 | /// Prints the default integer and float types. | |
788 | /// | |
789 | /// ```rust | |
790 | /// #![feature(type_name_of_val)] | |
791 | /// use std::any::type_name_of_val; | |
792 | /// | |
793 | /// let x = 1; | |
794 | /// println!("{}", type_name_of_val(&x)); | |
795 | /// let y = 1.0; | |
796 | /// println!("{}", type_name_of_val(&y)); | |
797 | /// ``` | |
3c0e092e | 798 | #[must_use] |
60c5eb7d | 799 | #[unstable(feature = "type_name_of_val", issue = "66359")] |
dfeec247 XL |
800 | #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] |
801 | pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str { | |
60c5eb7d XL |
802 | type_name::<T>() |
803 | } | |
923072b8 FG |
804 | |
805 | /////////////////////////////////////////////////////////////////////////////// | |
806 | // Provider trait | |
807 | /////////////////////////////////////////////////////////////////////////////// | |
808 | ||
809 | /// Trait implemented by a type which can dynamically provide values based on type. | |
810 | #[unstable(feature = "provide_any", issue = "96024")] | |
811 | pub trait Provider { | |
812 | /// Data providers should implement this method to provide *all* values they are able to | |
813 | /// provide by using `demand`. | |
814 | /// | |
815 | /// Note that the `provide_*` methods on `Demand` have short-circuit semantics: if an earlier | |
816 | /// method has successfully provided a value, then later methods will not get an opportunity to | |
817 | /// provide. | |
818 | /// | |
819 | /// # Examples | |
820 | /// | |
821 | /// Provides a reference to a field with type `String` as a `&str`, and a value of | |
822 | /// type `i32`. | |
823 | /// | |
824 | /// ```rust | |
825 | /// # #![feature(provide_any)] | |
826 | /// use std::any::{Provider, Demand}; | |
827 | /// # struct SomeConcreteType { field: String, num_field: i32 } | |
828 | /// | |
829 | /// impl Provider for SomeConcreteType { | |
830 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
831 | /// demand.provide_ref::<str>(&self.field) | |
f2b60f7d | 832 | /// .provide_value::<i32>(self.num_field); |
923072b8 FG |
833 | /// } |
834 | /// } | |
835 | /// ``` | |
836 | #[unstable(feature = "provide_any", issue = "96024")] | |
837 | fn provide<'a>(&'a self, demand: &mut Demand<'a>); | |
838 | } | |
839 | ||
840 | /// Request a value from the `Provider`. | |
841 | /// | |
842 | /// # Examples | |
843 | /// | |
844 | /// Get a string value from a provider. | |
845 | /// | |
846 | /// ```rust | |
847 | /// # #![feature(provide_any)] | |
848 | /// use std::any::{Provider, request_value}; | |
849 | /// | |
064997fb FG |
850 | /// fn get_string(provider: &impl Provider) -> String { |
851 | /// request_value::<String>(provider).unwrap() | |
923072b8 FG |
852 | /// } |
853 | /// ``` | |
854 | #[unstable(feature = "provide_any", issue = "96024")] | |
064997fb | 855 | pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T> |
923072b8 FG |
856 | where |
857 | T: 'static, | |
923072b8 | 858 | { |
064997fb | 859 | request_by_type_tag::<'a, tags::Value<T>>(provider) |
923072b8 FG |
860 | } |
861 | ||
862 | /// Request a reference from the `Provider`. | |
863 | /// | |
864 | /// # Examples | |
865 | /// | |
866 | /// Get a string reference from a provider. | |
867 | /// | |
868 | /// ```rust | |
869 | /// # #![feature(provide_any)] | |
870 | /// use std::any::{Provider, request_ref}; | |
871 | /// | |
064997fb FG |
872 | /// fn get_str(provider: &impl Provider) -> &str { |
873 | /// request_ref::<str>(provider).unwrap() | |
923072b8 FG |
874 | /// } |
875 | /// ``` | |
876 | #[unstable(feature = "provide_any", issue = "96024")] | |
064997fb | 877 | pub fn request_ref<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<&'a T> |
923072b8 FG |
878 | where |
879 | T: 'static + ?Sized, | |
923072b8 | 880 | { |
064997fb | 881 | request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(provider) |
923072b8 FG |
882 | } |
883 | ||
884 | /// Request a specific value by tag from the `Provider`. | |
064997fb | 885 | fn request_by_type_tag<'a, I>(provider: &'a (impl Provider + ?Sized)) -> Option<I::Reified> |
923072b8 FG |
886 | where |
887 | I: tags::Type<'a>, | |
923072b8 FG |
888 | { |
889 | let mut tagged = TaggedOption::<'a, I>(None); | |
890 | provider.provide(tagged.as_demand()); | |
891 | tagged.0 | |
892 | } | |
893 | ||
894 | /////////////////////////////////////////////////////////////////////////////// | |
895 | // Demand and its methods | |
896 | /////////////////////////////////////////////////////////////////////////////// | |
897 | ||
898 | /// A helper object for providing data by type. | |
899 | /// | |
900 | /// A data provider provides values by calling this type's provide methods. | |
901 | #[unstable(feature = "provide_any", issue = "96024")] | |
49aad941 | 902 | #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435 |
923072b8 FG |
903 | pub struct Demand<'a>(dyn Erased<'a> + 'a); |
904 | ||
905 | impl<'a> Demand<'a> { | |
906 | /// Create a new `&mut Demand` from a `&mut dyn Erased` trait object. | |
907 | fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Demand<'a> { | |
908 | // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since | |
909 | // `Demand` is repr(transparent). | |
910 | unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Demand<'a>) } | |
911 | } | |
912 | ||
913 | /// Provide a value or other type with only static lifetimes. | |
914 | /// | |
915 | /// # Examples | |
916 | /// | |
f2b60f7d FG |
917 | /// Provides an `u8`. |
918 | /// | |
919 | /// ```rust | |
920 | /// #![feature(provide_any)] | |
921 | /// | |
922 | /// use std::any::{Provider, Demand}; | |
923 | /// # struct SomeConcreteType { field: u8 } | |
924 | /// | |
925 | /// impl Provider for SomeConcreteType { | |
926 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
927 | /// demand.provide_value::<u8>(self.field); | |
928 | /// } | |
929 | /// } | |
930 | /// ``` | |
931 | #[unstable(feature = "provide_any", issue = "96024")] | |
932 | pub fn provide_value<T>(&mut self, value: T) -> &mut Self | |
933 | where | |
934 | T: 'static, | |
935 | { | |
936 | self.provide::<tags::Value<T>>(value) | |
937 | } | |
938 | ||
939 | /// Provide a value or other type with only static lifetimes computed using a closure. | |
940 | /// | |
941 | /// # Examples | |
942 | /// | |
923072b8 FG |
943 | /// Provides a `String` by cloning. |
944 | /// | |
945 | /// ```rust | |
f2b60f7d FG |
946 | /// #![feature(provide_any)] |
947 | /// | |
923072b8 FG |
948 | /// use std::any::{Provider, Demand}; |
949 | /// # struct SomeConcreteType { field: String } | |
950 | /// | |
951 | /// impl Provider for SomeConcreteType { | |
952 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
f2b60f7d | 953 | /// demand.provide_value_with::<String>(|| self.field.clone()); |
923072b8 FG |
954 | /// } |
955 | /// } | |
956 | /// ``` | |
957 | #[unstable(feature = "provide_any", issue = "96024")] | |
f2b60f7d | 958 | pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self |
923072b8 FG |
959 | where |
960 | T: 'static, | |
923072b8 | 961 | { |
064997fb | 962 | self.provide_with::<tags::Value<T>>(fulfil) |
923072b8 FG |
963 | } |
964 | ||
f2b60f7d | 965 | /// Provide a reference. The referee type must be bounded by `'static`, |
923072b8 FG |
966 | /// but may be unsized. |
967 | /// | |
968 | /// # Examples | |
969 | /// | |
970 | /// Provides a reference to a field as a `&str`. | |
971 | /// | |
972 | /// ```rust | |
f2b60f7d FG |
973 | /// #![feature(provide_any)] |
974 | /// | |
923072b8 FG |
975 | /// use std::any::{Provider, Demand}; |
976 | /// # struct SomeConcreteType { field: String } | |
977 | /// | |
978 | /// impl Provider for SomeConcreteType { | |
979 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
980 | /// demand.provide_ref::<str>(&self.field); | |
981 | /// } | |
982 | /// } | |
983 | /// ``` | |
984 | #[unstable(feature = "provide_any", issue = "96024")] | |
985 | pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self { | |
986 | self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value) | |
987 | } | |
988 | ||
f2b60f7d FG |
989 | /// Provide a reference computed using a closure. The referee type |
990 | /// must be bounded by `'static`, but may be unsized. | |
991 | /// | |
992 | /// # Examples | |
993 | /// | |
994 | /// Provides a reference to a field as a `&str`. | |
995 | /// | |
996 | /// ```rust | |
997 | /// #![feature(provide_any)] | |
998 | /// | |
999 | /// use std::any::{Provider, Demand}; | |
1000 | /// # struct SomeConcreteType { business: String, party: String } | |
1001 | /// # fn today_is_a_weekday() -> bool { true } | |
1002 | /// | |
1003 | /// impl Provider for SomeConcreteType { | |
1004 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
1005 | /// demand.provide_ref_with::<str>(|| { | |
1006 | /// if today_is_a_weekday() { | |
1007 | /// &self.business | |
1008 | /// } else { | |
1009 | /// &self.party | |
1010 | /// } | |
1011 | /// }); | |
1012 | /// } | |
1013 | /// } | |
1014 | /// ``` | |
1015 | #[unstable(feature = "provide_any", issue = "96024")] | |
1016 | pub fn provide_ref_with<T: ?Sized + 'static>( | |
1017 | &mut self, | |
1018 | fulfil: impl FnOnce() -> &'a T, | |
1019 | ) -> &mut Self { | |
1020 | self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil) | |
1021 | } | |
1022 | ||
923072b8 FG |
1023 | /// Provide a value with the given `Type` tag. |
1024 | fn provide<I>(&mut self, value: I::Reified) -> &mut Self | |
1025 | where | |
1026 | I: tags::Type<'a>, | |
1027 | { | |
1028 | if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { | |
1029 | res.0 = Some(value); | |
1030 | } | |
1031 | self | |
1032 | } | |
1033 | ||
1034 | /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work. | |
064997fb | 1035 | fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self |
923072b8 FG |
1036 | where |
1037 | I: tags::Type<'a>, | |
923072b8 FG |
1038 | { |
1039 | if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { | |
1040 | res.0 = Some(fulfil()); | |
1041 | } | |
1042 | self | |
1043 | } | |
f2b60f7d FG |
1044 | |
1045 | /// Check if the `Demand` would be satisfied if provided with a | |
1046 | /// value of the specified type. If the type does not match or has | |
1047 | /// already been provided, returns false. | |
1048 | /// | |
1049 | /// # Examples | |
1050 | /// | |
1051 | /// Check if an `u8` still needs to be provided and then provides | |
1052 | /// it. | |
1053 | /// | |
1054 | /// ```rust | |
1055 | /// #![feature(provide_any)] | |
1056 | /// | |
1057 | /// use std::any::{Provider, Demand}; | |
1058 | /// | |
1059 | /// struct Parent(Option<u8>); | |
1060 | /// | |
1061 | /// impl Provider for Parent { | |
1062 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
1063 | /// if let Some(v) = self.0 { | |
1064 | /// demand.provide_value::<u8>(v); | |
1065 | /// } | |
1066 | /// } | |
1067 | /// } | |
1068 | /// | |
1069 | /// struct Child { | |
1070 | /// parent: Parent, | |
1071 | /// } | |
1072 | /// | |
1073 | /// impl Child { | |
1074 | /// // Pretend that this takes a lot of resources to evaluate. | |
1075 | /// fn an_expensive_computation(&self) -> Option<u8> { | |
1076 | /// Some(99) | |
1077 | /// } | |
1078 | /// } | |
1079 | /// | |
1080 | /// impl Provider for Child { | |
1081 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
1082 | /// // In general, we don't know if this call will provide | |
1083 | /// // an `u8` value or not... | |
1084 | /// self.parent.provide(demand); | |
1085 | /// | |
1086 | /// // ...so we check to see if the `u8` is needed before | |
1087 | /// // we run our expensive computation. | |
1088 | /// if demand.would_be_satisfied_by_value_of::<u8>() { | |
1089 | /// if let Some(v) = self.an_expensive_computation() { | |
1090 | /// demand.provide_value::<u8>(v); | |
1091 | /// } | |
1092 | /// } | |
1093 | /// | |
1094 | /// // The demand will be satisfied now, regardless of if | |
1095 | /// // the parent provided the value or we did. | |
1096 | /// assert!(!demand.would_be_satisfied_by_value_of::<u8>()); | |
1097 | /// } | |
1098 | /// } | |
1099 | /// | |
1100 | /// let parent = Parent(Some(42)); | |
1101 | /// let child = Child { parent }; | |
1102 | /// assert_eq!(Some(42), std::any::request_value::<u8>(&child)); | |
1103 | /// | |
1104 | /// let parent = Parent(None); | |
1105 | /// let child = Child { parent }; | |
1106 | /// assert_eq!(Some(99), std::any::request_value::<u8>(&child)); | |
1107 | /// ``` | |
1108 | #[unstable(feature = "provide_any", issue = "96024")] | |
1109 | pub fn would_be_satisfied_by_value_of<T>(&self) -> bool | |
1110 | where | |
1111 | T: 'static, | |
1112 | { | |
1113 | self.would_be_satisfied_by::<tags::Value<T>>() | |
1114 | } | |
1115 | ||
1116 | /// Check if the `Demand` would be satisfied if provided with a | |
1117 | /// reference to a value of the specified type. If the type does | |
1118 | /// not match or has already been provided, returns false. | |
1119 | /// | |
1120 | /// # Examples | |
1121 | /// | |
1122 | /// Check if a `&str` still needs to be provided and then provides | |
1123 | /// it. | |
1124 | /// | |
1125 | /// ```rust | |
1126 | /// #![feature(provide_any)] | |
1127 | /// | |
1128 | /// use std::any::{Provider, Demand}; | |
1129 | /// | |
1130 | /// struct Parent(Option<String>); | |
1131 | /// | |
1132 | /// impl Provider for Parent { | |
1133 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
1134 | /// if let Some(v) = &self.0 { | |
1135 | /// demand.provide_ref::<str>(v); | |
1136 | /// } | |
1137 | /// } | |
1138 | /// } | |
1139 | /// | |
1140 | /// struct Child { | |
1141 | /// parent: Parent, | |
1142 | /// name: String, | |
1143 | /// } | |
1144 | /// | |
1145 | /// impl Child { | |
1146 | /// // Pretend that this takes a lot of resources to evaluate. | |
1147 | /// fn an_expensive_computation(&self) -> Option<&str> { | |
1148 | /// Some(&self.name) | |
1149 | /// } | |
1150 | /// } | |
1151 | /// | |
1152 | /// impl Provider for Child { | |
1153 | /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { | |
1154 | /// // In general, we don't know if this call will provide | |
1155 | /// // a `str` reference or not... | |
1156 | /// self.parent.provide(demand); | |
1157 | /// | |
1158 | /// // ...so we check to see if the `&str` is needed before | |
1159 | /// // we run our expensive computation. | |
1160 | /// if demand.would_be_satisfied_by_ref_of::<str>() { | |
1161 | /// if let Some(v) = self.an_expensive_computation() { | |
1162 | /// demand.provide_ref::<str>(v); | |
1163 | /// } | |
1164 | /// } | |
1165 | /// | |
1166 | /// // The demand will be satisfied now, regardless of if | |
1167 | /// // the parent provided the reference or we did. | |
1168 | /// assert!(!demand.would_be_satisfied_by_ref_of::<str>()); | |
1169 | /// } | |
1170 | /// } | |
1171 | /// | |
1172 | /// let parent = Parent(Some("parent".into())); | |
1173 | /// let child = Child { parent, name: "child".into() }; | |
1174 | /// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child)); | |
1175 | /// | |
1176 | /// let parent = Parent(None); | |
1177 | /// let child = Child { parent, name: "child".into() }; | |
1178 | /// assert_eq!(Some("child"), std::any::request_ref::<str>(&child)); | |
1179 | /// ``` | |
1180 | #[unstable(feature = "provide_any", issue = "96024")] | |
1181 | pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool | |
1182 | where | |
1183 | T: ?Sized + 'static, | |
1184 | { | |
1185 | self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>() | |
1186 | } | |
1187 | ||
1188 | fn would_be_satisfied_by<I>(&self) -> bool | |
1189 | where | |
1190 | I: tags::Type<'a>, | |
1191 | { | |
1192 | matches!(self.0.downcast::<I>(), Some(TaggedOption(None))) | |
1193 | } | |
923072b8 FG |
1194 | } |
1195 | ||
1196 | #[unstable(feature = "provide_any", issue = "96024")] | |
1197 | impl<'a> fmt::Debug for Demand<'a> { | |
1198 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1199 | f.debug_struct("Demand").finish_non_exhaustive() | |
1200 | } | |
1201 | } | |
1202 | ||
1203 | /////////////////////////////////////////////////////////////////////////////// | |
1204 | // Type tags | |
1205 | /////////////////////////////////////////////////////////////////////////////// | |
1206 | ||
1207 | mod tags { | |
1208 | //! Type tags are used to identify a type using a separate value. This module includes type tags | |
1209 | //! for some very common types. | |
1210 | //! | |
1211 | //! Currently type tags are not exposed to the user. But in the future, if you want to use the | |
1212 | //! Provider API with more complex types (typically those including lifetime parameters), you | |
1213 | //! will need to write your own tags. | |
1214 | ||
1215 | use crate::marker::PhantomData; | |
1216 | ||
1217 | /// This trait is implemented by specific tag types in order to allow | |
1218 | /// describing a type which can be requested for a given lifetime `'a`. | |
1219 | /// | |
1220 | /// A few example implementations for type-driven tags can be found in this | |
1221 | /// module, although crates may also implement their own tags for more | |
1222 | /// complex types with internal lifetimes. | |
1223 | pub trait Type<'a>: Sized + 'static { | |
1224 | /// The type of values which may be tagged by this tag for the given | |
1225 | /// lifetime. | |
1226 | type Reified: 'a; | |
1227 | } | |
1228 | ||
1229 | /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a | |
1230 | /// `?Sized` bound). E.g., `str`. | |
1231 | pub trait MaybeSizedType<'a>: Sized + 'static { | |
1232 | type Reified: 'a + ?Sized; | |
1233 | } | |
1234 | ||
1235 | impl<'a, T: Type<'a>> MaybeSizedType<'a> for T { | |
1236 | type Reified = T::Reified; | |
1237 | } | |
1238 | ||
1239 | /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements. | |
1240 | #[derive(Debug)] | |
1241 | pub struct Value<T: 'static>(PhantomData<T>); | |
1242 | ||
1243 | impl<'a, T: 'static> Type<'a> for Value<T> { | |
1244 | type Reified = T; | |
1245 | } | |
1246 | ||
1247 | /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound). | |
1248 | #[derive(Debug)] | |
1249 | pub struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>); | |
1250 | ||
1251 | impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> { | |
1252 | type Reified = T; | |
1253 | } | |
1254 | ||
1255 | /// Type-based tag for reference types (`&'a T`, where T is represented by | |
1256 | /// `<I as MaybeSizedType<'a>>::Reified`. | |
1257 | #[derive(Debug)] | |
1258 | pub struct Ref<I>(PhantomData<I>); | |
1259 | ||
1260 | impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> { | |
1261 | type Reified = &'a I::Reified; | |
1262 | } | |
1263 | } | |
1264 | ||
1265 | /// An `Option` with a type tag `I`. | |
1266 | /// | |
1267 | /// Since this struct implements `Erased`, the type can be erased to make a dynamically typed | |
1268 | /// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically | |
1269 | /// checked for the concrete type, there is some degree of type safety. | |
1270 | #[repr(transparent)] | |
1271 | struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>); | |
1272 | ||
1273 | impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> { | |
1274 | fn as_demand(&mut self) -> &mut Demand<'a> { | |
1275 | Demand::new(self as &mut (dyn Erased<'a> + 'a)) | |
1276 | } | |
1277 | } | |
1278 | ||
1279 | /// Represents a type-erased but identifiable object. | |
1280 | /// | |
1281 | /// This trait is exclusively implemented by the `TaggedOption` type. | |
1282 | unsafe trait Erased<'a>: 'a { | |
1283 | /// The `TypeId` of the erased type. | |
1284 | fn tag_id(&self) -> TypeId; | |
1285 | } | |
1286 | ||
1287 | unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> { | |
1288 | fn tag_id(&self) -> TypeId { | |
1289 | TypeId::of::<I>() | |
1290 | } | |
1291 | } | |
1292 | ||
1293 | #[unstable(feature = "provide_any", issue = "96024")] | |
1294 | impl<'a> dyn Erased<'a> + 'a { | |
1295 | /// Returns some reference to the dynamic value if it is tagged with `I`, | |
1296 | /// or `None` otherwise. | |
1297 | #[inline] | |
f2b60f7d FG |
1298 | fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>> |
1299 | where | |
1300 | I: tags::Type<'a>, | |
1301 | { | |
1302 | if self.tag_id() == TypeId::of::<I>() { | |
1303 | // SAFETY: Just checked whether we're pointing to an I. | |
1304 | Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() }) | |
1305 | } else { | |
1306 | None | |
1307 | } | |
1308 | } | |
1309 | ||
1310 | /// Returns some mutable reference to the dynamic value if it is tagged with `I`, | |
1311 | /// or `None` otherwise. | |
1312 | #[inline] | |
923072b8 FG |
1313 | fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>> |
1314 | where | |
1315 | I: tags::Type<'a>, | |
1316 | { | |
1317 | if self.tag_id() == TypeId::of::<I>() { | |
1318 | // SAFETY: Just checked whether we're pointing to an I. | |
1319 | Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() }) | |
1320 | } else { | |
1321 | None | |
1322 | } | |
1323 | } | |
1324 | } |