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
89use crate::fmt;
90use crate::hash;
91use 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")]
115pub 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")]
140impl<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")]
151impl 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")]
161impl 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")]
168impl 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
174impl 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
333impl 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
465impl 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")]
607pub 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")]
614impl PartialEq for TypeId {
615 #[inline]
616 fn eq(&self, other: &Self) -> bool {
617 self.t == other.t
618 }
619}
620
621impl 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")]
650impl 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")]
699pub 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")]
739pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
740 type_name::<T>()
741}
742