Skip to main content

## Module any

1.6.0 · Source
Expand description

Utilities for dynamic typing or type reflection.

## §`Any` and `TypeId`

`Any` itself can be used to get a `TypeId`, and has more features when used as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` and `downcast_ref` methods, to test if the contained value is of a given type, and to get a reference to the inner value as a type. As `&mut dyn Any`, there is also the `downcast_mut` method, for getting a mutable reference to the inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to convert to a `Box<T>`. See the `Box` documentation for the full details.

Note that `&dyn Any` is limited to testing whether a value is of a specified concrete type, and cannot be used to test whether a type implements a trait.

## §Smart pointers and `dyn Any`

One piece of behavior to keep in mind when using `Any` as a trait object, especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply calling `.type_id()` on the value will produce the `TypeId` of the container, not the underlying trait object. This can be avoided by converting the smart pointer into a `&dyn Any` instead, which will return the object’s `TypeId`. For example:

    use std::any::{Any, TypeId};

    let boxed: Box<dyn Any> = Box::new(3_i32);

    // You're more likely to want this:
    let actual_id = (&*boxed).type_id();
    // ... than this:
    let boxed_id = boxed.type_id();

    assert_eq!(actual_id, TypeId::of::<i32>());
    assert_eq!(boxed_id, TypeId::of::<Box<dyn Any>>());

### §Examples

Consider a situation where we want to log a value passed to a function. We know the value we’re working on implements `Debug`, but we don’t know its concrete type. We want to give special treatment to certain types: in this case printing out the length of `String` values prior to their value. We don’t know the concrete type of our value at compile time, so we need to use runtime reflection instead.

    use std::fmt::Debug;
    use std::any::Any;

    // Logger function for any type that implements `Debug`.
    fn log<T: Any + Debug>(value: &T) {
        let value_any = value as &dyn Any;

        // Try to convert our value to a `String`. If successful, we want to
        // output the `String`'s length as well as its value. If not, it's a
        // different type: just print it out unadorned.
        match value_any.downcast_ref::<String>() {
            Some(as_string) => {
                println!("String ({}): {}", as_string.len(), as_string);
            }
            None => {
                println!("{value:?}");
            }
        }
    }

    // This function wants to log its parameter out prior to doing work with it.
    fn do_work<T: Any + Debug>(value: &T) {
        log(value);
        // ...do some other work
    }

    fn main() {
        let my_string = "Hello World".to_string();
        do_work(&my_string);

        let my_i8: i8 = 100;
        do_work(&my_i8);
    }

## Structs§

TypeId
  A `TypeId` represents a globally unique identifier for a type.

## Traits§

Any
  A trait to emulate dynamic typing.

## Functions§

type_name
  Returns the name of a type as a string slice.
type_name_of_val
  Returns the type name of the pointed-to value as a string slice.
try_as_dynExperimental
  Returns `Some(&U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`.
try_as_dyn_mutExperimental
  Returns `Some(&mut U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`.