1 | //! Utilities for dynamic typing or type reflection. |
2 | //! |
3 | //! # `Any` and `TypeId` |
4 | //! |
5 | //! `Any` itself can be used to get a `TypeId`, and has more features when used |
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 |
9 | //! is also the `downcast_mut` method, for getting a mutable reference to the |
10 | //! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to |
11 | //! convert to a `Box<T>`. See the [`Box`] documentation for the full details. |
12 | //! |
13 | //! Note that `&dyn Any` is limited to testing whether a value is of a specified |
14 | //! concrete type, and cannot be used to test whether a type implements a trait. |
15 | //! |
16 | //! [`Box`]: ../../std/boxed/struct.Box.html |
17 | //! |
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 | //! |
41 | //! ## Examples |
42 | //! |
43 | //! Consider a situation where we want to log a value passed to a function. |
44 | //! We know the value we're working on implements `Debug`, but we don't know its |
45 | //! concrete type. We want to give special treatment to certain types: in this |
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 |
51 | //! use std::fmt::Debug; |
52 | //! use std::any::Any; |
53 | //! |
54 | //! // Logger function for any type that implements `Debug`. |
55 | //! fn log<T: Any + Debug>(value: &T) { |
56 | //! let value_any = value as &dyn Any; |
57 | //! |
58 | //! // Try to convert our value to a `String`. If successful, we want to |
59 | //! // output the `String`'s length as well as its value. If not, it's a |
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 => { |
66 | //! println!("{value:?}" ); |
67 | //! } |
68 | //! } |
69 | //! } |
70 | //! |
71 | //! // This function wants to log its parameter out prior to doing work with it. |
72 | //! fn do_work<T: Any + Debug>(value: &T) { |
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 | //! ``` |
85 | //! |
86 | |
87 | #![stable (feature = "rust1" , since = "1.0.0" )] |
88 | |
89 | use crate::fmt; |
90 | use crate::hash; |
91 | use crate::intrinsics; |
92 | |
93 | /////////////////////////////////////////////////////////////////////////////// |
94 | // Any trait |
95 | /////////////////////////////////////////////////////////////////////////////// |
96 | |
97 | /// A trait to emulate dynamic typing. |
98 | /// |
99 | /// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. |
100 | /// See the [module-level documentation][mod] for more details. |
101 | /// |
102 | /// [mod]: crate::any |
103 | // This trait is not unsafe, though we rely on the specifics of it's sole impl's |
104 | // `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be |
105 | // a problem, but because the only impl of `Any` is a blanket implementation, no |
106 | // other code can implement `Any`. |
107 | // |
108 | // We could plausibly make this trait unsafe -- it would not cause breakage, |
109 | // since we control all the implementations -- but we choose not to as that's |
110 | // both not really necessary and may confuse users about the distinction of |
111 | // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, |
112 | // but we would likely want to indicate as such in documentation). |
113 | #[stable (feature = "rust1" , since = "1.0.0" )] |
114 | #[cfg_attr (not(test), rustc_diagnostic_item = "Any" )] |
115 | pub trait Any: 'static { |
116 | /// Gets the `TypeId` of `self`. |
117 | /// |
118 | /// If called on a `dyn Any` trait object |
119 | /// (or a trait object of a subtrait of `Any`), |
120 | /// this returns the `TypeId` of the underlying |
121 | /// concrete type, not that of `dyn Any` itself. |
122 | /// |
123 | /// # Examples |
124 | /// |
125 | /// ``` |
126 | /// use std::any::{Any, TypeId}; |
127 | /// |
128 | /// fn is_string(s: &dyn Any) -> bool { |
129 | /// TypeId::of::<String>() == s.type_id() |
130 | /// } |
131 | /// |
132 | /// assert_eq!(is_string(&0), false); |
133 | /// assert_eq!(is_string(&"cookie monster" .to_string()), true); |
134 | /// ``` |
135 | #[stable (feature = "get_type_id" , since = "1.34.0" )] |
136 | fn type_id(&self) -> TypeId; |
137 | } |
138 | |
139 | #[stable (feature = "rust1" , since = "1.0.0" )] |
140 | impl<T: 'static + ?Sized> Any for T { |
141 | fn type_id(&self) -> TypeId { |
142 | TypeId::of::<T>() |
143 | } |
144 | } |
145 | |
146 | /////////////////////////////////////////////////////////////////////////////// |
147 | // Extension methods for Any trait objects. |
148 | /////////////////////////////////////////////////////////////////////////////// |
149 | |
150 | #[stable (feature = "rust1" , since = "1.0.0" )] |
151 | impl fmt::Debug for dyn Any { |
152 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
153 | f.debug_struct(name:"Any" ).finish_non_exhaustive() |
154 | } |
155 | } |
156 | |
157 | // Ensure that the result of e.g., joining a thread can be printed and |
158 | // hence used with `unwrap`. May eventually no longer be needed if |
159 | // dispatch works with upcasting. |
160 | #[stable (feature = "rust1" , since = "1.0.0" )] |
161 | impl fmt::Debug for dyn Any + Send { |
162 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
163 | f.debug_struct(name:"Any" ).finish_non_exhaustive() |
164 | } |
165 | } |
166 | |
167 | #[stable (feature = "any_send_sync_methods" , since = "1.28.0" )] |
168 | impl fmt::Debug for dyn Any + Send + Sync { |
169 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
170 | f.debug_struct(name:"Any" ).finish_non_exhaustive() |
171 | } |
172 | } |
173 | |
174 | impl dyn Any { |
175 | /// Returns `true` if the inner type is the same as `T`. |
176 | /// |
177 | /// # Examples |
178 | /// |
179 | /// ``` |
180 | /// use std::any::Any; |
181 | /// |
182 | /// fn is_string(s: &dyn Any) { |
183 | /// if s.is::<String>() { |
184 | /// println!("It's a string!" ); |
185 | /// } else { |
186 | /// println!("Not a string..." ); |
187 | /// } |
188 | /// } |
189 | /// |
190 | /// is_string(&0); |
191 | /// is_string(&"cookie monster" .to_string()); |
192 | /// ``` |
193 | #[stable (feature = "rust1" , since = "1.0.0" )] |
194 | #[inline ] |
195 | pub fn is<T: Any>(&self) -> bool { |
196 | // Get `TypeId` of the type this function is instantiated with. |
197 | let t = TypeId::of::<T>(); |
198 | |
199 | // Get `TypeId` of the type in the trait object (`self`). |
200 | let concrete = self.type_id(); |
201 | |
202 | // Compare both `TypeId`s on equality. |
203 | t == concrete |
204 | } |
205 | |
206 | /// Returns some reference to the inner value if it is of type `T`, or |
207 | /// `None` if it isn't. |
208 | /// |
209 | /// # Examples |
210 | /// |
211 | /// ``` |
212 | /// use std::any::Any; |
213 | /// |
214 | /// fn print_if_string(s: &dyn Any) { |
215 | /// if let Some(string) = s.downcast_ref::<String>() { |
216 | /// println!("It's a string({}): '{}'" , string.len(), string); |
217 | /// } else { |
218 | /// println!("Not a string..." ); |
219 | /// } |
220 | /// } |
221 | /// |
222 | /// print_if_string(&0); |
223 | /// print_if_string(&"cookie monster" .to_string()); |
224 | /// ``` |
225 | #[stable (feature = "rust1" , since = "1.0.0" )] |
226 | #[inline ] |
227 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { |
228 | if self.is::<T>() { |
229 | // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
230 | // that check for memory safety because we have implemented Any for all types; no other |
231 | // impls can exist as they would conflict with our impl. |
232 | unsafe { Some(self.downcast_ref_unchecked()) } |
233 | } else { |
234 | None |
235 | } |
236 | } |
237 | |
238 | /// Returns some mutable reference to the inner value if it is of type `T`, or |
239 | /// `None` if it isn't. |
240 | /// |
241 | /// # Examples |
242 | /// |
243 | /// ``` |
244 | /// use std::any::Any; |
245 | /// |
246 | /// fn modify_if_u32(s: &mut dyn Any) { |
247 | /// if let Some(num) = s.downcast_mut::<u32>() { |
248 | /// *num = 42; |
249 | /// } |
250 | /// } |
251 | /// |
252 | /// let mut x = 10u32; |
253 | /// let mut s = "starlord" .to_string(); |
254 | /// |
255 | /// modify_if_u32(&mut x); |
256 | /// modify_if_u32(&mut s); |
257 | /// |
258 | /// assert_eq!(x, 42); |
259 | /// assert_eq!(&s, "starlord" ); |
260 | /// ``` |
261 | #[stable (feature = "rust1" , since = "1.0.0" )] |
262 | #[inline ] |
263 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { |
264 | if self.is::<T>() { |
265 | // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
266 | // that check for memory safety because we have implemented Any for all types; no other |
267 | // impls can exist as they would conflict with our impl. |
268 | unsafe { Some(self.downcast_mut_unchecked()) } |
269 | } else { |
270 | None |
271 | } |
272 | } |
273 | |
274 | /// Returns a reference to the inner value as type `dyn T`. |
275 | /// |
276 | /// # Examples |
277 | /// |
278 | /// ``` |
279 | /// #![feature(downcast_unchecked)] |
280 | /// |
281 | /// use std::any::Any; |
282 | /// |
283 | /// let x: Box<dyn Any> = Box::new(1_usize); |
284 | /// |
285 | /// unsafe { |
286 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); |
287 | /// } |
288 | /// ``` |
289 | /// |
290 | /// # Safety |
291 | /// |
292 | /// The contained value must be of type `T`. Calling this method |
293 | /// with the incorrect type is *undefined behavior*. |
294 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
295 | #[inline ] |
296 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { |
297 | debug_assert!(self.is::<T>()); |
298 | // SAFETY: caller guarantees that T is the correct type |
299 | unsafe { &*(self as *const dyn Any as *const T) } |
300 | } |
301 | |
302 | /// Returns a mutable reference to the inner value as type `dyn T`. |
303 | /// |
304 | /// # Examples |
305 | /// |
306 | /// ``` |
307 | /// #![feature(downcast_unchecked)] |
308 | /// |
309 | /// use std::any::Any; |
310 | /// |
311 | /// let mut x: Box<dyn Any> = Box::new(1_usize); |
312 | /// |
313 | /// unsafe { |
314 | /// *x.downcast_mut_unchecked::<usize>() += 1; |
315 | /// } |
316 | /// |
317 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); |
318 | /// ``` |
319 | /// |
320 | /// # Safety |
321 | /// |
322 | /// The contained value must be of type `T`. Calling this method |
323 | /// with the incorrect type is *undefined behavior*. |
324 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
325 | #[inline ] |
326 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { |
327 | debug_assert!(self.is::<T>()); |
328 | // SAFETY: caller guarantees that T is the correct type |
329 | unsafe { &mut *(self as *mut dyn Any as *mut T) } |
330 | } |
331 | } |
332 | |
333 | impl dyn Any + Send { |
334 | /// Forwards to the method defined on the type `dyn Any`. |
335 | /// |
336 | /// # Examples |
337 | /// |
338 | /// ``` |
339 | /// use std::any::Any; |
340 | /// |
341 | /// fn is_string(s: &(dyn Any + Send)) { |
342 | /// if s.is::<String>() { |
343 | /// println!("It's a string!" ); |
344 | /// } else { |
345 | /// println!("Not a string..." ); |
346 | /// } |
347 | /// } |
348 | /// |
349 | /// is_string(&0); |
350 | /// is_string(&"cookie monster" .to_string()); |
351 | /// ``` |
352 | #[stable (feature = "rust1" , since = "1.0.0" )] |
353 | #[inline ] |
354 | pub fn is<T: Any>(&self) -> bool { |
355 | <dyn Any>::is::<T>(self) |
356 | } |
357 | |
358 | /// Forwards to the method defined on the type `dyn Any`. |
359 | /// |
360 | /// # Examples |
361 | /// |
362 | /// ``` |
363 | /// use std::any::Any; |
364 | /// |
365 | /// fn print_if_string(s: &(dyn Any + Send)) { |
366 | /// if let Some(string) = s.downcast_ref::<String>() { |
367 | /// println!("It's a string({}): '{}'" , string.len(), string); |
368 | /// } else { |
369 | /// println!("Not a string..." ); |
370 | /// } |
371 | /// } |
372 | /// |
373 | /// print_if_string(&0); |
374 | /// print_if_string(&"cookie monster" .to_string()); |
375 | /// ``` |
376 | #[stable (feature = "rust1" , since = "1.0.0" )] |
377 | #[inline ] |
378 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { |
379 | <dyn Any>::downcast_ref::<T>(self) |
380 | } |
381 | |
382 | /// Forwards to the method defined on the type `dyn Any`. |
383 | /// |
384 | /// # Examples |
385 | /// |
386 | /// ``` |
387 | /// use std::any::Any; |
388 | /// |
389 | /// fn modify_if_u32(s: &mut (dyn Any + Send)) { |
390 | /// if let Some(num) = s.downcast_mut::<u32>() { |
391 | /// *num = 42; |
392 | /// } |
393 | /// } |
394 | /// |
395 | /// let mut x = 10u32; |
396 | /// let mut s = "starlord" .to_string(); |
397 | /// |
398 | /// modify_if_u32(&mut x); |
399 | /// modify_if_u32(&mut s); |
400 | /// |
401 | /// assert_eq!(x, 42); |
402 | /// assert_eq!(&s, "starlord" ); |
403 | /// ``` |
404 | #[stable (feature = "rust1" , since = "1.0.0" )] |
405 | #[inline ] |
406 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { |
407 | <dyn Any>::downcast_mut::<T>(self) |
408 | } |
409 | |
410 | /// Forwards to the method defined on the type `dyn Any`. |
411 | /// |
412 | /// # Examples |
413 | /// |
414 | /// ``` |
415 | /// #![feature(downcast_unchecked)] |
416 | /// |
417 | /// use std::any::Any; |
418 | /// |
419 | /// let x: Box<dyn Any> = Box::new(1_usize); |
420 | /// |
421 | /// unsafe { |
422 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); |
423 | /// } |
424 | /// ``` |
425 | /// |
426 | /// # Safety |
427 | /// |
428 | /// Same as the method on the type `dyn Any`. |
429 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
430 | #[inline ] |
431 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { |
432 | // SAFETY: guaranteed by caller |
433 | unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) } |
434 | } |
435 | |
436 | /// Forwards to the method defined on the type `dyn Any`. |
437 | /// |
438 | /// # Examples |
439 | /// |
440 | /// ``` |
441 | /// #![feature(downcast_unchecked)] |
442 | /// |
443 | /// use std::any::Any; |
444 | /// |
445 | /// let mut x: Box<dyn Any> = Box::new(1_usize); |
446 | /// |
447 | /// unsafe { |
448 | /// *x.downcast_mut_unchecked::<usize>() += 1; |
449 | /// } |
450 | /// |
451 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); |
452 | /// ``` |
453 | /// |
454 | /// # Safety |
455 | /// |
456 | /// Same as the method on the type `dyn Any`. |
457 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
458 | #[inline ] |
459 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { |
460 | // SAFETY: guaranteed by caller |
461 | unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) } |
462 | } |
463 | } |
464 | |
465 | impl dyn Any + Send + Sync { |
466 | /// Forwards to the method defined on the type `Any`. |
467 | /// |
468 | /// # Examples |
469 | /// |
470 | /// ``` |
471 | /// use std::any::Any; |
472 | /// |
473 | /// fn is_string(s: &(dyn Any + Send + Sync)) { |
474 | /// if s.is::<String>() { |
475 | /// println!("It's a string!" ); |
476 | /// } else { |
477 | /// println!("Not a string..." ); |
478 | /// } |
479 | /// } |
480 | /// |
481 | /// is_string(&0); |
482 | /// is_string(&"cookie monster" .to_string()); |
483 | /// ``` |
484 | #[stable (feature = "any_send_sync_methods" , since = "1.28.0" )] |
485 | #[inline ] |
486 | pub fn is<T: Any>(&self) -> bool { |
487 | <dyn Any>::is::<T>(self) |
488 | } |
489 | |
490 | /// Forwards to the method defined on the type `Any`. |
491 | /// |
492 | /// # Examples |
493 | /// |
494 | /// ``` |
495 | /// use std::any::Any; |
496 | /// |
497 | /// fn print_if_string(s: &(dyn Any + Send + Sync)) { |
498 | /// if let Some(string) = s.downcast_ref::<String>() { |
499 | /// println!("It's a string({}): '{}'" , string.len(), string); |
500 | /// } else { |
501 | /// println!("Not a string..." ); |
502 | /// } |
503 | /// } |
504 | /// |
505 | /// print_if_string(&0); |
506 | /// print_if_string(&"cookie monster" .to_string()); |
507 | /// ``` |
508 | #[stable (feature = "any_send_sync_methods" , since = "1.28.0" )] |
509 | #[inline ] |
510 | pub fn downcast_ref<T: Any>(&self) -> Option<&T> { |
511 | <dyn Any>::downcast_ref::<T>(self) |
512 | } |
513 | |
514 | /// Forwards to the method defined on the type `Any`. |
515 | /// |
516 | /// # Examples |
517 | /// |
518 | /// ``` |
519 | /// use std::any::Any; |
520 | /// |
521 | /// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) { |
522 | /// if let Some(num) = s.downcast_mut::<u32>() { |
523 | /// *num = 42; |
524 | /// } |
525 | /// } |
526 | /// |
527 | /// let mut x = 10u32; |
528 | /// let mut s = "starlord" .to_string(); |
529 | /// |
530 | /// modify_if_u32(&mut x); |
531 | /// modify_if_u32(&mut s); |
532 | /// |
533 | /// assert_eq!(x, 42); |
534 | /// assert_eq!(&s, "starlord" ); |
535 | /// ``` |
536 | #[stable (feature = "any_send_sync_methods" , since = "1.28.0" )] |
537 | #[inline ] |
538 | pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { |
539 | <dyn Any>::downcast_mut::<T>(self) |
540 | } |
541 | |
542 | /// Forwards to the method defined on the type `Any`. |
543 | /// |
544 | /// # Examples |
545 | /// |
546 | /// ``` |
547 | /// #![feature(downcast_unchecked)] |
548 | /// |
549 | /// use std::any::Any; |
550 | /// |
551 | /// let x: Box<dyn Any> = Box::new(1_usize); |
552 | /// |
553 | /// unsafe { |
554 | /// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1); |
555 | /// } |
556 | /// ``` |
557 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
558 | #[inline ] |
559 | pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T { |
560 | // SAFETY: guaranteed by caller |
561 | unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) } |
562 | } |
563 | |
564 | /// Forwards to the method defined on the type `Any`. |
565 | /// |
566 | /// # Examples |
567 | /// |
568 | /// ``` |
569 | /// #![feature(downcast_unchecked)] |
570 | /// |
571 | /// use std::any::Any; |
572 | /// |
573 | /// let mut x: Box<dyn Any> = Box::new(1_usize); |
574 | /// |
575 | /// unsafe { |
576 | /// *x.downcast_mut_unchecked::<usize>() += 1; |
577 | /// } |
578 | /// |
579 | /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2); |
580 | /// ``` |
581 | #[unstable (feature = "downcast_unchecked" , issue = "90850" )] |
582 | #[inline ] |
583 | pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T { |
584 | // SAFETY: guaranteed by caller |
585 | unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) } |
586 | } |
587 | } |
588 | |
589 | /////////////////////////////////////////////////////////////////////////////// |
590 | // TypeID and its methods |
591 | /////////////////////////////////////////////////////////////////////////////// |
592 | |
593 | /// A `TypeId` represents a globally unique identifier for a type. |
594 | /// |
595 | /// Each `TypeId` is an opaque object which does not allow inspection of what's |
596 | /// inside but does allow basic operations such as cloning, comparison, |
597 | /// printing, and showing. |
598 | /// |
599 | /// A `TypeId` is currently only available for types which ascribe to `'static`, |
600 | /// but this limitation may be removed in the future. |
601 | /// |
602 | /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth |
603 | /// noting that the hashes and ordering will vary between Rust releases. Beware |
604 | /// of relying on them inside of your code! |
605 | #[derive (Clone, Copy, Debug, Eq, PartialOrd, Ord)] |
606 | #[stable (feature = "rust1" , since = "1.0.0" )] |
607 | pub struct TypeId { |
608 | // We avoid using `u128` because that imposes higher alignment requirements on many platforms. |
609 | // See issue #115620 for more information. |
610 | t: (u64, u64), |
611 | } |
612 | |
613 | #[stable (feature = "rust1" , since = "1.0.0" )] |
614 | impl PartialEq for TypeId { |
615 | #[inline ] |
616 | fn eq(&self, other: &Self) -> bool { |
617 | self.t == other.t |
618 | } |
619 | } |
620 | |
621 | impl TypeId { |
622 | /// Returns the `TypeId` of the type this generic function has been |
623 | /// instantiated with. |
624 | /// |
625 | /// # Examples |
626 | /// |
627 | /// ``` |
628 | /// use std::any::{Any, TypeId}; |
629 | /// |
630 | /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool { |
631 | /// TypeId::of::<String>() == TypeId::of::<T>() |
632 | /// } |
633 | /// |
634 | /// assert_eq!(is_string(&0), false); |
635 | /// assert_eq!(is_string(&"cookie monster" .to_string()), true); |
636 | /// ``` |
637 | #[must_use ] |
638 | #[stable (feature = "rust1" , since = "1.0.0" )] |
639 | #[rustc_const_unstable (feature = "const_type_id" , issue = "77125" )] |
640 | pub const fn of<T: ?Sized + 'static>() -> TypeId { |
641 | let t: u128 = intrinsics::type_id::<T>(); |
642 | |
643 | let t1 = (t >> 64) as u64; |
644 | let t2 = t as u64; |
645 | TypeId { t: (t1, t2) } |
646 | } |
647 | } |
648 | |
649 | #[stable (feature = "rust1" , since = "1.0.0" )] |
650 | impl hash::Hash for TypeId { |
651 | #[inline ] |
652 | fn hash<H: hash::Hasher>(&self, state: &mut H) { |
653 | // We only hash the lower 64 bits of our (128 bit) internal numeric ID, |
654 | // because: |
655 | // - The hashing algorithm which backs `TypeId` is expected to be |
656 | // unbiased and high quality, meaning further mixing would be somewhat |
657 | // redundant compared to choosing (the lower) 64 bits arbitrarily. |
658 | // - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd |
659 | // get from hashing the full value would probably not be useful |
660 | // (especially given the previous point about the lower 64 bits being |
661 | // high quality on their own). |
662 | // - It is correct to do so -- only hashing a subset of `self` is still |
663 | // with an `Eq` implementation that considers the entire value, as |
664 | // ours does. |
665 | self.t.1.hash(state); |
666 | } |
667 | } |
668 | |
669 | /// Returns the name of a type as a string slice. |
670 | /// |
671 | /// # Note |
672 | /// |
673 | /// This is intended for diagnostic use. The exact contents and format of the |
674 | /// string returned are not specified, other than being a best-effort |
675 | /// description of the type. For example, amongst the strings |
676 | /// that `type_name::<Option<String>>()` might return are `"Option<String>"` and |
677 | /// `"std::option::Option<std::string::String>"`. |
678 | /// |
679 | /// The returned string must not be considered to be a unique identifier of a |
680 | /// type as multiple types may map to the same type name. Similarly, there is no |
681 | /// guarantee that all parts of a type will appear in the returned string: for |
682 | /// example, lifetime specifiers are currently not included. In addition, the |
683 | /// output may change between versions of the compiler. |
684 | /// |
685 | /// The current implementation uses the same infrastructure as compiler |
686 | /// diagnostics and debuginfo, but this is not guaranteed. |
687 | /// |
688 | /// # Examples |
689 | /// |
690 | /// ```rust |
691 | /// assert_eq!( |
692 | /// std::any::type_name::<Option<String>>(), |
693 | /// "core::option::Option<alloc::string::String>" , |
694 | /// ); |
695 | /// ``` |
696 | #[must_use ] |
697 | #[stable (feature = "type_name" , since = "1.38.0" )] |
698 | #[rustc_const_unstable (feature = "const_type_name" , issue = "63084" )] |
699 | pub const fn type_name<T: ?Sized>() -> &'static str { |
700 | intrinsics::type_name::<T>() |
701 | } |
702 | |
703 | /// Returns the type name of the pointed-to value as a string slice. |
704 | /// |
705 | /// This is the same as `type_name::<T>()`, but can be used where the type of a |
706 | /// variable is not easily available. |
707 | /// |
708 | /// # Note |
709 | /// |
710 | /// Like [`type_name`], this is intended for diagnostic use and the exact output is not |
711 | /// guaranteed. It provides a best-effort description, but the output may change between |
712 | /// versions of the compiler. |
713 | /// |
714 | /// In short: use this for debugging, avoid using the output to affect program behavior. More |
715 | /// information is available at [`type_name`]. |
716 | /// |
717 | /// Additionally, this function does not resolve trait objects. This means that |
718 | /// `type_name_of_val(&7u32 as &dyn Debug)` may return `"dyn Debug"`, but will not return `"u32"` |
719 | /// at this time. |
720 | /// |
721 | /// # Examples |
722 | /// |
723 | /// Prints the default integer and float types. |
724 | /// |
725 | /// ```rust |
726 | /// use std::any::type_name_of_val; |
727 | /// |
728 | /// let s = "foo" ; |
729 | /// let x: i32 = 1; |
730 | /// let y: f32 = 1.0; |
731 | /// |
732 | /// assert!(type_name_of_val(&s).contains("str" )); |
733 | /// assert!(type_name_of_val(&x).contains("i32" )); |
734 | /// assert!(type_name_of_val(&y).contains("f32" )); |
735 | /// ``` |
736 | #[must_use ] |
737 | #[stable (feature = "type_name_of_val" , since = "1.76.0" )] |
738 | #[rustc_const_unstable (feature = "const_type_name" , issue = "63084" )] |
739 | pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str { |
740 | type_name::<T>() |
741 | } |
742 | |