# Module core::any

1.0.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>>());

Run

### Examples

Consider a situation where we want to log out 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);
    }

Run

## `Provider` and `Demand`

`Provider` and the associated APIs support generic, type-driven access to data, and a mechanism for implementers to provide such data. The key parts of the interface are the `Provider` trait for objects which can provide data, and the `request_value` and `request_ref` functions for requesting data from an object which implements `Provider`. Generally, end users should not call `request_*` directly, they are helper functions for intermediate implementers to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is no safety concern here; intermediate implementers can typically support methods rather than free functions and use more specific names.

Typically, a data provider is a trait object of a trait which extends `Provider`. A user will request data from a trait object by specifying the type of the data.

### Data flow

- A user requests an object of a specific type, which is delegated to `request_value` or `request_ref`
- `request_*` creates a `Demand` object and passes it to `Provider::provide`
- The data provider’s implementation of `Provider::provide` tries providing values of different types using `Demand::provide_*`. If the type matches the type requested by the user, the value will be stored in the `Demand` object.
- `request_*` unpacks the `Demand` object and returns any stored value to the user.

### Examples

    use std::any::{Provider, Demand, request_ref};

    // Definition of MyTrait, a data provider.
    trait MyTrait: Provider {
        // ...
    }

    // Methods on `MyTrait` trait objects.
    impl dyn MyTrait + '_ {
        /// Get a reference to a field of the implementing struct.
        pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
            request_ref::<T>(self)
        }
    }

    // Downstream implementation of `MyTrait` and `Provider`.
    impl MyTrait for SomeConcreteType {
        // ...
    }

    impl Provider for SomeConcreteType {
        fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
            // Provide a string reference. We could provide multiple values with
            // different types here.
            demand.provide_ref::<String>(&self.some_string);
        }
    }

    // Downstream usage of `MyTrait`.
    fn use_my_trait(obj: &dyn MyTrait) {
        // Request a &String from obj.
        let _ = obj.get_context_by_ref::<String>().unwrap();
    }

Run

In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`.

## Structs

- Demand Experimental
  A helper object for providing data by type.
- TypeId
  A `TypeId` represents a globally unique identifier for a type.

## Traits

- Provider Experimental
  Trait implemented by a type which can dynamically provide values based on type.
- Any
  A trait to emulate dynamic typing.

## Functions

- request_ref Experimental
  Request a reference from the `Provider`.
- request_value Experimental
  Request a value from the `Provider`.
- type_name_of_val Experimental
  Returns the name of the type of the pointed-to value as a string slice. This is the same as `type_name::<T>()`, but can be used where the type of a variable is not easily available.
- type_name
  Returns the name of a type as a string slice.