2022-04-30 12:01:31 -05:00
|
|
|
//! Utilities for dynamic typing or type reflection.
|
2021-12-15 16:17:16 +00:00
|
|
|
//!
|
|
|
|
//! # `Any` and `TypeId`
|
2013-12-06 12:33:08 -05:00
|
|
|
//!
|
2014-07-06 17:30:01 +01:00
|
|
|
//! `Any` itself can be used to get a `TypeId`, and has more features when used
|
2019-10-13 18:48:07 +07:00
|
|
|
//! 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
|
2015-08-26 13:59:39 -04:00
|
|
|
//! is also the `downcast_mut` method, for getting a mutable reference to the
|
2019-10-13 18:48:07 +07:00
|
|
|
//! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to
|
2015-12-11 18:44:11 -05:00
|
|
|
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
|
2014-07-06 17:30:01 +01:00
|
|
|
//!
|
2019-10-13 19:03:21 +07:00
|
|
|
//! Note that `&dyn Any` is limited to testing whether a value is of a specified
|
2014-07-06 17:30:01 +01:00
|
|
|
//! concrete type, and cannot be used to test whether a type implements a trait.
|
|
|
|
//!
|
2016-03-07 23:55:52 -08:00
|
|
|
//! [`Box`]: ../../std/boxed/struct.Box.html
|
2015-12-11 18:44:11 -05:00
|
|
|
//!
|
2020-12-09 22:43:59 +00:00
|
|
|
//! # Smart pointers and `dyn Any`
|
|
|
|
//!
|
|
|
|
//! One piece of behavior to keep in mind when using `Any` as a trait object,
|
2020-12-09 23:13:24 +00:00
|
|
|
//! especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply
|
2020-12-09 22:43:59 +00:00
|
|
|
//! calling `.type_id()` on the value will produce the `TypeId` of the
|
2020-12-09 23:13:24 +00:00
|
|
|
//! *container*, not the underlying trait object. This can be avoided by
|
2020-12-09 22:43:59 +00:00
|
|
|
//! converting the smart pointer into a `&dyn Any` instead, which will return
|
2020-12-09 23:13:24 +00:00
|
|
|
//! the object's `TypeId`. For example:
|
|
|
|
//!
|
2020-12-09 22:43:59 +00:00
|
|
|
//! ```
|
|
|
|
//! 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>>());
|
|
|
|
//! ```
|
|
|
|
//!
|
2021-12-15 16:17:16 +00:00
|
|
|
//! ## Examples
|
2014-07-06 17:30:01 +01:00
|
|
|
//!
|
|
|
|
//! Consider a situation where we want to log out a value passed to a function.
|
2015-02-05 15:04:07 +03:00
|
|
|
//! We know the value we're working on implements Debug, but we don't know its
|
2019-02-09 21:23:30 +00:00
|
|
|
//! concrete type. We want to give special treatment to certain types: in this
|
2014-07-06 17:30:01 +01:00
|
|
|
//! 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.
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2015-01-20 15:45:07 -08:00
|
|
|
//! use std::fmt::Debug;
|
2015-01-01 01:13:08 -05:00
|
|
|
//! use std::any::Any;
|
2014-07-06 17:30:01 +01:00
|
|
|
//!
|
2015-01-20 15:45:07 -08:00
|
|
|
//! // Logger function for any type that implements Debug.
|
|
|
|
//! fn log<T: Any + Debug>(value: &T) {
|
2018-11-19 15:59:21 +09:00
|
|
|
//! let value_any = value as &dyn Any;
|
2014-07-06 17:30:01 +01:00
|
|
|
//!
|
2019-02-09 21:23:30 +00:00
|
|
|
//! // 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
|
2014-07-06 17:30:01 +01:00
|
|
|
//! // different type: just print it out unadorned.
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
//! match value_any.downcast_ref::<String>() {
|
2014-07-06 17:30:01 +01:00
|
|
|
//! Some(as_string) => {
|
2015-01-06 16:16:35 -08:00
|
|
|
//! println!("String ({}): {}", as_string.len(), as_string);
|
2014-07-06 17:30:01 +01:00
|
|
|
//! }
|
|
|
|
//! None => {
|
2022-02-12 23:16:17 +04:00
|
|
|
//! println!("{value:?}");
|
2014-07-06 17:30:01 +01:00
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // This function wants to log its parameter out prior to doing work with it.
|
2015-03-24 15:55:29 -04:00
|
|
|
//! fn do_work<T: Any + Debug>(value: &T) {
|
2014-07-06 17:30:01 +01:00
|
|
|
//! 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);
|
|
|
|
//! }
|
|
|
|
//! ```
|
2021-12-15 16:17:16 +00:00
|
|
|
//!
|
|
|
|
//! # `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`]
|
2022-04-12 10:49:53 +01:00
|
|
|
//! functions for requesting data from an object which implements `Provider`. Generally, end users
|
2021-12-15 16:17:16 +00:00
|
|
|
//! should not call `request_*` directly, they are helper functions for intermediate implementers
|
2022-05-11 10:12:22 +01:00
|
|
|
//! to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is
|
2022-06-10 20:53:49 -07:00
|
|
|
//! no safety concern here; intermediate implementers can typically support methods rather than
|
2022-05-11 10:12:22 +01:00
|
|
|
//! free functions and use more specific names.
|
2021-12-15 16:17:16 +00:00
|
|
|
//!
|
|
|
|
//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will
|
2022-04-12 10:49:53 +01:00
|
|
|
//! request data from a trait object by specifying the type of the data.
|
2021-12-15 16:17:16 +00:00
|
|
|
//!
|
|
|
|
//! ## Data flow
|
|
|
|
//!
|
2022-04-12 10:49:53 +01:00
|
|
|
//! * A user requests an object of a specific type, which is delegated to `request_value` or
|
|
|
|
//! `request_ref`
|
2021-12-15 16:17:16 +00:00
|
|
|
//! * `request_*` creates a `Demand` object and passes it to `Provider::provide`
|
2022-04-12 10:49:53 +01:00
|
|
|
//! * The data provider's implementation of `Provider::provide` tries providing values of
|
2021-12-15 16:17:16 +00:00
|
|
|
//! different types using `Demand::provide_*`. If the type matches the type requested by
|
2022-04-12 10:49:53 +01:00
|
|
|
//! the user, the value will be stored in the `Demand` object.
|
2021-12-15 16:17:16 +00:00
|
|
|
//! * `request_*` unpacks the `Demand` object and returns any stored value to the user.
|
|
|
|
//!
|
|
|
|
//! ## Examples
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! # #![feature(provide_any)]
|
|
|
|
//! use std::any::{Provider, Demand, request_ref};
|
|
|
|
//!
|
2022-04-12 10:49:53 +01:00
|
|
|
//! // Definition of MyTrait, a data provider.
|
2021-12-15 16:17:16 +00:00
|
|
|
//! trait MyTrait: Provider {
|
|
|
|
//! // ...
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // Methods on `MyTrait` trait objects.
|
|
|
|
//! impl dyn MyTrait + '_ {
|
2022-04-12 10:49:53 +01:00
|
|
|
//! /// Get a reference to a field of the implementing struct.
|
|
|
|
//! pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
|
2022-06-13 09:29:55 +01:00
|
|
|
//! request_ref::<T>(self)
|
2021-12-15 16:17:16 +00:00
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // Downstream implementation of `MyTrait` and `Provider`.
|
|
|
|
//! # struct SomeConcreteType { some_string: String }
|
|
|
|
//! impl MyTrait for SomeConcreteType {
|
|
|
|
//! // ...
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! impl Provider for SomeConcreteType {
|
2022-04-12 21:38:27 +01:00
|
|
|
//! fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
2022-04-12 10:49:53 +01:00
|
|
|
//! // Provide a string reference. We could provide multiple values with
|
|
|
|
//! // different types here.
|
2022-04-12 21:38:27 +01:00
|
|
|
//! demand.provide_ref::<String>(&self.some_string);
|
2021-12-15 16:17:16 +00:00
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // Downstream usage of `MyTrait`.
|
|
|
|
//! fn use_my_trait(obj: &dyn MyTrait) {
|
|
|
|
//! // Request a &String from obj.
|
2022-04-12 10:49:53 +01:00
|
|
|
//! let _ = obj.get_context_by_ref::<String>().unwrap();
|
2021-12-15 16:17:16 +00:00
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then
|
2022-12-27 16:16:22 +01:00
|
|
|
//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`.
|
2013-10-11 23:20:34 +02:00
|
|
|
|
2015-01-23 21:48:20 -08:00
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
|
2019-04-15 11:23:21 +09:00
|
|
|
use crate::fmt;
|
|
|
|
use crate::intrinsics;
|
2014-02-01 04:35:36 +08:00
|
|
|
|
2013-10-11 23:20:34 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Any trait
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-11-29 20:47:16 +02:00
|
|
|
/// A trait to emulate dynamic typing.
|
2014-06-12 19:54:03 +12:00
|
|
|
///
|
2016-06-07 20:19:08 +03:00
|
|
|
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
|
2015-04-06 08:36:37 -07:00
|
|
|
/// See the [module-level documentation][mod] for more details.
|
2015-03-24 12:15:49 -04:00
|
|
|
///
|
2020-08-14 20:50:38 +02:00
|
|
|
/// [mod]: crate::any
|
2019-12-22 07:54:18 -05:00
|
|
|
// This trait is not unsafe, though we rely on the specifics of it's sole impl's
|
|
|
|
// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be
|
|
|
|
// a problem, but because the only impl of `Any` is a blanket implementation, no
|
|
|
|
// other code can implement `Any`.
|
|
|
|
//
|
|
|
|
// We could plausibly make this trait unsafe -- it would not cause breakage,
|
|
|
|
// since we control all the implementations -- but we choose not to as that's
|
|
|
|
// both not really necessary and may confuse users about the distinction of
|
|
|
|
// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call,
|
|
|
|
// but we would likely want to indicate as such in documentation).
|
2015-01-23 21:48:20 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-07-15 23:51:34 +02:00
|
|
|
#[cfg_attr(not(test), rustc_diagnostic_item = "Any")]
|
2016-10-06 18:28:27 +13:00
|
|
|
pub trait Any: 'static {
|
2015-04-13 10:21:32 -04:00
|
|
|
/// Gets the `TypeId` of `self`.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::{Any, TypeId};
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn is_string(s: &dyn Any) -> bool {
|
2019-01-22 14:25:27 +01:00
|
|
|
/// TypeId::of::<String>() == s.type_id()
|
2016-07-10 15:09:55 +02:00
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!(is_string(&0), false);
|
|
|
|
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2019-01-22 14:25:27 +01:00
|
|
|
#[stable(feature = "get_type_id", since = "1.34.0")]
|
|
|
|
fn type_id(&self) -> TypeId;
|
2013-10-30 16:32:33 -07:00
|
|
|
}
|
|
|
|
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2016-10-06 18:28:27 +13:00
|
|
|
impl<T: 'static + ?Sized> Any for T {
|
2019-01-22 14:25:27 +01:00
|
|
|
fn type_id(&self) -> TypeId {
|
|
|
|
TypeId::of::<T>()
|
|
|
|
}
|
2013-10-11 23:20:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Extension methods for Any trait objects.
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2015-03-30 17:50:31 -04:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2018-07-10 20:39:28 +02:00
|
|
|
impl fmt::Debug for dyn Any {
|
2019-04-19 01:37:12 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-21 14:51:04 +02:00
|
|
|
f.debug_struct("Any").finish_non_exhaustive()
|
2015-03-30 17:50:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-27 02:59:49 +00:00
|
|
|
// Ensure that the result of e.g., joining a thread can be printed and
|
2015-04-09 17:23:49 -07:00
|
|
|
// hence used with `unwrap`. May eventually no longer be needed if
|
|
|
|
// dispatch works with upcasting.
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2018-07-10 20:39:28 +02:00
|
|
|
impl fmt::Debug for dyn Any + Send {
|
2019-04-19 01:37:12 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-21 14:51:04 +02:00
|
|
|
f.debug_struct("Any").finish_non_exhaustive()
|
2015-04-09 17:23:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-16 23:09:58 -07:00
|
|
|
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
2018-07-10 20:39:28 +02:00
|
|
|
impl fmt::Debug for dyn Any + Send + Sync {
|
2019-04-19 01:37:12 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-21 14:51:04 +02:00
|
|
|
f.debug_struct("Any").finish_non_exhaustive()
|
2018-05-16 23:09:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-10 20:39:28 +02:00
|
|
|
impl dyn Any {
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Returns `true` if the inner type is the same as `T`.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn is_string(s: &dyn Any) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if s.is::<String>() {
|
|
|
|
/// println!("It's a string!");
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// is_string(&0);
|
|
|
|
/// is_string(&"cookie monster".to_string());
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2013-10-11 23:20:34 +02:00
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn is<T: Any>(&self) -> bool {
|
2019-09-05 17:15:28 +01:00
|
|
|
// Get `TypeId` of the type this function is instantiated with.
|
2013-10-11 23:20:34 +02:00
|
|
|
let t = TypeId::of::<T>();
|
|
|
|
|
2020-03-22 11:41:07 +01:00
|
|
|
// Get `TypeId` of the type in the trait object (`self`).
|
2019-01-22 14:25:27 +01:00
|
|
|
let concrete = self.type_id();
|
2013-10-11 23:20:34 +02:00
|
|
|
|
2019-09-05 17:15:28 +01:00
|
|
|
// Compare both `TypeId`s on equality.
|
2019-01-22 14:25:27 +01:00
|
|
|
t == concrete
|
2013-10-11 23:20:34 +02:00
|
|
|
}
|
|
|
|
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Returns some reference to the inner value if it is of type `T`, or
|
2015-01-01 01:13:08 -05:00
|
|
|
/// `None` if it isn't.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn print_if_string(s: &dyn Any) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if let Some(string) = s.downcast_ref::<String>() {
|
|
|
|
/// println!("It's a string({}): '{}'", string.len(), string);
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// print_if_string(&0);
|
|
|
|
/// print_if_string(&"cookie monster".to_string());
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2013-10-11 23:20:34 +02:00
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
2013-10-11 23:20:34 +02:00
|
|
|
if self.is::<T>() {
|
2020-01-28 20:53:45 -05:00
|
|
|
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
|
|
|
// that check for memory safety because we have implemented Any for all types; no other
|
|
|
|
// impls can exist as they would conflict with our impl.
|
2021-11-12 22:53:26 -05:00
|
|
|
unsafe { Some(self.downcast_ref_unchecked()) }
|
2013-10-11 23:20:34 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Returns some mutable reference to the inner value if it is of type `T`, or
|
2013-10-11 23:20:34 +02:00
|
|
|
/// `None` if it isn't.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn modify_if_u32(s: &mut dyn Any) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if let Some(num) = s.downcast_mut::<u32>() {
|
|
|
|
/// *num = 42;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// let mut x = 10u32;
|
|
|
|
/// let mut s = "starlord".to_string();
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// modify_if_u32(&mut x);
|
|
|
|
/// modify_if_u32(&mut s);
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!(x, 42);
|
|
|
|
/// assert_eq!(&s, "starlord");
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2013-10-11 23:20:34 +02:00
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
2013-10-11 23:20:34 +02:00
|
|
|
if self.is::<T>() {
|
2020-01-28 20:53:45 -05:00
|
|
|
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
|
|
|
// that check for memory safety because we have implemented Any for all types; no other
|
|
|
|
// impls can exist as they would conflict with our impl.
|
2021-11-12 22:53:26 -05:00
|
|
|
unsafe { Some(self.downcast_mut_unchecked()) }
|
2013-10-11 23:20:34 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2021-11-12 22:53:26 -05:00
|
|
|
|
|
|
|
/// Returns a reference to the inner value as type `dyn T`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// The contained value must be of type `T`. Calling this method
|
|
|
|
/// with the incorrect type is *undefined behavior*.
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
|
|
|
debug_assert!(self.is::<T>());
|
|
|
|
// SAFETY: caller guarantees that T is the correct type
|
|
|
|
unsafe { &*(self as *const dyn Any as *const T) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a mutable reference to the inner value as type `dyn T`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// The contained value must be of type `T`. Calling this method
|
|
|
|
/// with the incorrect type is *undefined behavior*.
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
|
|
|
debug_assert!(self.is::<T>());
|
|
|
|
// SAFETY: caller guarantees that T is the correct type
|
|
|
|
unsafe { &mut *(self as *mut dyn Any as *mut T) }
|
|
|
|
}
|
2013-10-11 23:20:34 +02:00
|
|
|
}
|
2015-01-14 16:08:07 -08:00
|
|
|
|
2018-07-10 20:39:28 +02:00
|
|
|
impl dyn Any + Send {
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Forwards to the method defined on the type `dyn Any`.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn is_string(s: &(dyn Any + Send)) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if s.is::<String>() {
|
|
|
|
/// println!("It's a string!");
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// is_string(&0);
|
|
|
|
/// is_string(&"cookie monster".to_string());
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-02-17 05:17:19 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn is<T: Any>(&self) -> bool {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::is::<T>(self)
|
2015-02-17 05:17:19 -05:00
|
|
|
}
|
|
|
|
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Forwards to the method defined on the type `dyn Any`.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn print_if_string(s: &(dyn Any + Send)) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if let Some(string) = s.downcast_ref::<String>() {
|
|
|
|
/// println!("It's a string({}): '{}'", string.len(), string);
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// print_if_string(&0);
|
|
|
|
/// print_if_string(&"cookie monster".to_string());
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-02-17 05:17:19 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::downcast_ref::<T>(self)
|
2015-02-17 05:17:19 -05:00
|
|
|
}
|
|
|
|
|
2021-11-12 22:53:26 -05:00
|
|
|
/// Forwards to the method defined on the type `dyn Any`.
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn modify_if_u32(s: &mut (dyn Any + Send)) {
|
2016-07-10 15:09:55 +02:00
|
|
|
/// if let Some(num) = s.downcast_mut::<u32>() {
|
|
|
|
/// *num = 42;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// let mut x = 10u32;
|
|
|
|
/// let mut s = "starlord".to_string();
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// modify_if_u32(&mut x);
|
|
|
|
/// modify_if_u32(&mut s);
|
2016-07-10 15:09:55 +02:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!(x, 42);
|
|
|
|
/// assert_eq!(&s, "starlord");
|
2016-07-10 15:09:55 +02:00
|
|
|
/// ```
|
2015-02-17 05:17:19 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
#[inline]
|
2015-03-24 15:55:29 -04:00
|
|
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::downcast_mut::<T>(self)
|
2015-02-17 05:17:19 -05:00
|
|
|
}
|
2021-11-12 22:53:26 -05:00
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `dyn Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Same as the method on the type `dyn Any`.
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
|
|
|
// SAFETY: guaranteed by caller
|
|
|
|
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `dyn Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Same as the method on the type `dyn Any`.
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
|
|
|
// SAFETY: guaranteed by caller
|
|
|
|
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
|
|
|
|
}
|
2015-02-17 05:17:19 -05:00
|
|
|
}
|
|
|
|
|
2018-07-10 20:39:28 +02:00
|
|
|
impl dyn Any + Send + Sync {
|
2018-05-16 23:09:58 -07:00
|
|
|
/// Forwards to the method defined on the type `Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn is_string(s: &(dyn Any + Send + Sync)) {
|
2018-05-16 23:09:58 -07:00
|
|
|
/// if s.is::<String>() {
|
|
|
|
/// println!("It's a string!");
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// is_string(&0);
|
|
|
|
/// is_string(&"cookie monster".to_string());
|
2018-05-16 23:09:58 -07:00
|
|
|
/// ```
|
|
|
|
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
|
|
|
#[inline]
|
|
|
|
pub fn is<T: Any>(&self) -> bool {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::is::<T>(self)
|
2018-05-16 23:09:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn print_if_string(s: &(dyn Any + Send + Sync)) {
|
2018-05-16 23:09:58 -07:00
|
|
|
/// if let Some(string) = s.downcast_ref::<String>() {
|
|
|
|
/// println!("It's a string({}): '{}'", string.len(), string);
|
|
|
|
/// } else {
|
|
|
|
/// println!("Not a string...");
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// print_if_string(&0);
|
|
|
|
/// print_if_string(&"cookie monster".to_string());
|
2018-05-16 23:09:58 -07:00
|
|
|
/// ```
|
|
|
|
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
|
|
|
#[inline]
|
|
|
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::downcast_ref::<T>(self)
|
2018-05-16 23:09:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
2018-11-19 15:59:21 +09:00
|
|
|
/// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) {
|
2018-05-16 23:09:58 -07:00
|
|
|
/// if let Some(num) = s.downcast_mut::<u32>() {
|
|
|
|
/// *num = 42;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// let mut x = 10u32;
|
|
|
|
/// let mut s = "starlord".to_string();
|
2018-05-16 23:09:58 -07:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// modify_if_u32(&mut x);
|
|
|
|
/// modify_if_u32(&mut s);
|
2018-05-16 23:09:58 -07:00
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!(x, 42);
|
|
|
|
/// assert_eq!(&s, "starlord");
|
2018-05-16 23:09:58 -07:00
|
|
|
/// ```
|
|
|
|
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
|
|
|
#[inline]
|
|
|
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
2021-03-07 18:47:39 +03:00
|
|
|
<dyn Any>::downcast_mut::<T>(self)
|
2018-05-16 23:09:58 -07:00
|
|
|
}
|
2021-11-12 22:53:26 -05:00
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
|
|
|
/// }
|
|
|
|
/// ```
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
|
|
|
// SAFETY: guaranteed by caller
|
|
|
|
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Forwards to the method defined on the type `Any`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(downcast_unchecked)]
|
|
|
|
///
|
|
|
|
/// use std::any::Any;
|
|
|
|
///
|
|
|
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
|
|
|
/// ```
|
2021-11-12 22:55:11 -05:00
|
|
|
#[unstable(feature = "downcast_unchecked", issue = "90850")]
|
2021-11-12 22:53:26 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
|
|
|
// SAFETY: guaranteed by caller
|
|
|
|
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
|
|
|
|
}
|
2018-05-16 23:09:58 -07:00
|
|
|
}
|
2015-02-17 05:17:19 -05:00
|
|
|
|
2015-01-14 16:08:07 -08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// TypeID and its methods
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// A `TypeId` represents a globally unique identifier for a type.
|
|
|
|
///
|
|
|
|
/// Each `TypeId` is an opaque object which does not allow inspection of what's
|
|
|
|
/// inside but does allow basic operations such as cloning, comparison,
|
|
|
|
/// printing, and showing.
|
|
|
|
///
|
|
|
|
/// A `TypeId` is currently only available for types which ascribe to `'static`,
|
|
|
|
/// but this limitation may be removed in the future.
|
2017-01-17 13:56:46 -08:00
|
|
|
///
|
|
|
|
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
|
|
|
|
/// noting that the hashes and ordering will vary between Rust releases. Beware
|
2018-07-03 13:13:49 -07:00
|
|
|
/// of relying on them inside of your code!
|
2017-01-10 18:19:01 -08:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
2015-01-23 21:48:20 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-01-14 16:08:07 -08:00
|
|
|
pub struct TypeId {
|
|
|
|
t: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeId {
|
2018-01-30 21:33:33 +01:00
|
|
|
/// Returns the `TypeId` of the type this generic function has been
|
|
|
|
/// instantiated with.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::any::{Any, TypeId};
|
|
|
|
///
|
|
|
|
/// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
|
|
|
|
/// TypeId::of::<String>() == TypeId::of::<T>()
|
|
|
|
/// }
|
|
|
|
///
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!(is_string(&0), false);
|
|
|
|
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
2018-01-30 21:33:33 +01:00
|
|
|
/// ```
|
2021-10-14 18:54:55 -04:00
|
|
|
#[must_use]
|
2018-01-30 21:33:33 +01:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-09-24 09:00:04 +10:00
|
|
|
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
2018-01-30 21:33:33 +01:00
|
|
|
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
2019-08-21 19:56:46 +02:00
|
|
|
TypeId { t: intrinsics::type_id::<T>() }
|
2018-01-30 21:33:33 +01:00
|
|
|
}
|
2015-01-14 16:08:07 -08:00
|
|
|
}
|
2019-04-17 19:38:17 -07:00
|
|
|
|
|
|
|
/// Returns the name of a type as a string slice.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// This is intended for diagnostic use. The exact contents and format of the
|
2020-05-04 14:28:58 +01:00
|
|
|
/// string returned are not specified, other than being a best-effort
|
|
|
|
/// description of the type. For example, amongst the strings
|
2020-05-12 16:54:29 +01:00
|
|
|
/// that `type_name::<Option<String>>()` might return are `"Option<String>"` and
|
2020-05-04 10:17:39 +01:00
|
|
|
/// `"std::option::Option<std::string::String>"`.
|
2019-04-17 19:38:17 -07:00
|
|
|
///
|
2020-05-04 10:17:39 +01:00
|
|
|
/// The returned string must not be considered to be a unique identifier of a
|
2020-05-04 11:01:31 +01:00
|
|
|
/// type as multiple types may map to the same type name. Similarly, there is no
|
|
|
|
/// guarantee that all parts of a type will appear in the returned string: for
|
|
|
|
/// example, lifetime specifiers are currently not included. In addition, the
|
2020-05-04 10:17:39 +01:00
|
|
|
/// output may change between versions of the compiler.
|
2019-04-17 19:38:17 -07:00
|
|
|
///
|
|
|
|
/// The current implementation uses the same infrastructure as compiler
|
|
|
|
/// diagnostics and debuginfo, but this is not guaranteed.
|
2019-10-16 16:50:07 +00:00
|
|
|
///
|
2019-11-19 10:18:53 +01:00
|
|
|
/// # Examples
|
2019-10-16 16:50:07 +00:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// assert_eq!(
|
|
|
|
/// std::any::type_name::<Option<String>>(),
|
|
|
|
/// "core::option::Option<alloc::string::String>",
|
|
|
|
/// );
|
|
|
|
/// ```
|
2021-10-14 18:54:55 -04:00
|
|
|
#[must_use]
|
2019-04-17 19:38:17 -07:00
|
|
|
#[stable(feature = "type_name", since = "1.38.0")]
|
2019-12-18 12:00:59 -05:00
|
|
|
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
2019-07-29 23:02:29 -04:00
|
|
|
pub const fn type_name<T: ?Sized>() -> &'static str {
|
2019-04-17 19:38:17 -07:00
|
|
|
intrinsics::type_name::<T>()
|
|
|
|
}
|
2019-11-19 10:18:53 +01:00
|
|
|
|
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// This is intended for diagnostic use. The exact contents and format of the
|
|
|
|
/// string are not specified, other than being a best-effort description of the
|
2020-01-18 14:43:08 +01:00
|
|
|
/// type. For example, `type_name_of_val::<Option<String>>(None)` could return
|
2019-11-19 10:18:53 +01:00
|
|
|
/// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
|
|
|
|
/// `"foobar"`. In addition, the output may change between versions of the
|
|
|
|
/// compiler.
|
|
|
|
///
|
2020-01-18 14:43:08 +01:00
|
|
|
/// This function does not resolve trait objects,
|
|
|
|
/// meaning that `type_name_of_val(&7u32 as &dyn Debug)`
|
|
|
|
/// may return `"dyn Debug"`, but not `"u32"`.
|
|
|
|
///
|
2019-11-19 10:18:53 +01:00
|
|
|
/// The type name should not be considered a unique identifier of a type;
|
|
|
|
/// multiple types may share the same type name.
|
|
|
|
///
|
|
|
|
/// The current implementation uses the same infrastructure as compiler
|
|
|
|
/// diagnostics and debuginfo, but this is not guaranteed.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Prints the default integer and float types.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #![feature(type_name_of_val)]
|
|
|
|
/// use std::any::type_name_of_val;
|
|
|
|
///
|
|
|
|
/// let x = 1;
|
|
|
|
/// println!("{}", type_name_of_val(&x));
|
|
|
|
/// let y = 1.0;
|
|
|
|
/// println!("{}", type_name_of_val(&y));
|
|
|
|
/// ```
|
2021-10-14 18:54:55 -04:00
|
|
|
#[must_use]
|
2019-11-19 10:18:53 +01:00
|
|
|
#[unstable(feature = "type_name_of_val", issue = "66359")]
|
2019-12-18 12:00:59 -05:00
|
|
|
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
2019-12-21 16:48:35 +00:00
|
|
|
pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
|
2019-11-19 10:18:53 +01:00
|
|
|
type_name::<T>()
|
|
|
|
}
|
2021-12-15 16:17:16 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Provider trait
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// Trait implemented by a type which can dynamically provide values based on type.
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2021-12-15 16:17:16 +00:00
|
|
|
pub trait Provider {
|
2022-04-12 10:49:53 +01:00
|
|
|
/// Data providers should implement this method to provide *all* values they are able to
|
|
|
|
/// provide by using `demand`.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
2022-05-11 10:12:22 +01:00
|
|
|
/// Note that the `provide_*` methods on `Demand` have short-circuit semantics: if an earlier
|
|
|
|
/// method has successfully provided a value, then later methods will not get an opportunity to
|
|
|
|
/// provide.
|
|
|
|
///
|
2022-04-12 21:38:27 +01:00
|
|
|
/// # Examples
|
|
|
|
///
|
2022-05-11 10:12:22 +01:00
|
|
|
/// Provides a reference to a field with type `String` as a `&str`, and a value of
|
|
|
|
/// type `i32`.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # #![feature(provide_any)]
|
|
|
|
/// use std::any::{Provider, Demand};
|
2022-05-11 10:12:22 +01:00
|
|
|
/// # struct SomeConcreteType { field: String, num_field: i32 }
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// impl Provider for SomeConcreteType {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
2022-05-11 10:12:22 +01:00
|
|
|
/// demand.provide_ref::<str>(&self.field)
|
2022-07-20 21:43:37 -04:00
|
|
|
/// .provide_value::<i32>(self.num_field);
|
2022-04-12 21:38:27 +01:00
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2022-04-12 10:49:53 +01:00
|
|
|
fn provide<'a>(&'a self, demand: &mut Demand<'a>);
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Request a value from the `Provider`.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Get a string value from a provider.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # #![feature(provide_any)]
|
|
|
|
/// use std::any::{Provider, request_value};
|
|
|
|
///
|
2022-06-13 09:29:55 +01:00
|
|
|
/// fn get_string(provider: &impl Provider) -> String {
|
|
|
|
/// request_value::<String>(provider).unwrap()
|
2022-04-12 21:38:27 +01:00
|
|
|
/// }
|
|
|
|
/// ```
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2022-06-13 09:29:55 +01:00
|
|
|
pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T>
|
2022-04-07 15:34:36 +01:00
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
2022-06-13 09:29:55 +01:00
|
|
|
request_by_type_tag::<'a, tags::Value<T>>(provider)
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Request a reference from the `Provider`.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Get a string reference from a provider.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # #![feature(provide_any)]
|
|
|
|
/// use std::any::{Provider, request_ref};
|
|
|
|
///
|
2022-06-13 09:29:55 +01:00
|
|
|
/// fn get_str(provider: &impl Provider) -> &str {
|
|
|
|
/// request_ref::<str>(provider).unwrap()
|
2022-04-12 21:38:27 +01:00
|
|
|
/// }
|
|
|
|
/// ```
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2022-06-13 09:29:55 +01:00
|
|
|
pub fn request_ref<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<&'a T>
|
2022-04-07 15:34:36 +01:00
|
|
|
where
|
|
|
|
T: 'static + ?Sized,
|
|
|
|
{
|
2022-06-13 09:29:55 +01:00
|
|
|
request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(provider)
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Request a specific value by tag from the `Provider`.
|
2022-06-13 09:29:55 +01:00
|
|
|
fn request_by_type_tag<'a, I>(provider: &'a (impl Provider + ?Sized)) -> Option<I::Reified>
|
2021-12-15 16:17:16 +00:00
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
let mut tagged = TaggedOption::<'a, I>(None);
|
|
|
|
provider.provide(tagged.as_demand());
|
|
|
|
tagged.0
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Demand and its methods
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-04-12 10:49:53 +01:00
|
|
|
/// A helper object for providing data by type.
|
2021-12-15 16:17:16 +00:00
|
|
|
///
|
2022-04-12 10:49:53 +01:00
|
|
|
/// A data provider provides values by calling this type's provide methods.
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2021-12-15 16:17:16 +00:00
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct Demand<'a>(dyn Erased<'a> + 'a);
|
|
|
|
|
|
|
|
impl<'a> Demand<'a> {
|
2022-05-11 10:12:22 +01:00
|
|
|
/// Create a new `&mut Demand` from a `&mut dyn Erased` trait object.
|
|
|
|
fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Demand<'a> {
|
|
|
|
// SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since
|
|
|
|
// `Demand` is repr(transparent).
|
|
|
|
unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Demand<'a>) }
|
|
|
|
}
|
|
|
|
|
2021-12-15 16:17:16 +00:00
|
|
|
/// Provide a value or other type with only static lifetimes.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
2022-07-20 21:43:37 -04:00
|
|
|
/// Provides an `u8`.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
/// # struct SomeConcreteType { field: u8 }
|
|
|
|
///
|
|
|
|
/// impl Provider for SomeConcreteType {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// demand.provide_value::<u8>(self.field);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
|
|
|
pub fn provide_value<T>(&mut self, value: T) -> &mut Self
|
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
|
|
|
self.provide::<tags::Value<T>>(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Provide a value or other type with only static lifetimes computed using a closure.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
2022-04-12 21:38:27 +01:00
|
|
|
/// Provides a `String` by cloning.
|
|
|
|
///
|
|
|
|
/// ```rust
|
2022-07-20 21:43:37 -04:00
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
2022-04-12 21:38:27 +01:00
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
/// # struct SomeConcreteType { field: String }
|
|
|
|
///
|
|
|
|
/// impl Provider for SomeConcreteType {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
2022-07-20 21:43:37 -04:00
|
|
|
/// demand.provide_value_with::<String>(|| self.field.clone());
|
2022-04-12 21:38:27 +01:00
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2022-07-20 21:43:37 -04:00
|
|
|
pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
|
2021-12-15 16:17:16 +00:00
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
2022-06-13 09:29:55 +01:00
|
|
|
self.provide_with::<tags::Value<T>>(fulfil)
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
|
2022-07-20 21:43:37 -04:00
|
|
|
/// Provide a reference. The referee type must be bounded by `'static`,
|
2022-04-12 10:49:53 +01:00
|
|
|
/// but may be unsized.
|
2022-04-12 21:38:27 +01:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Provides a reference to a field as a `&str`.
|
|
|
|
///
|
|
|
|
/// ```rust
|
2022-07-20 21:43:37 -04:00
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
2022-04-12 21:38:27 +01:00
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
/// # struct SomeConcreteType { field: String }
|
|
|
|
///
|
|
|
|
/// impl Provider for SomeConcreteType {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// demand.provide_ref::<str>(&self.field);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2021-12-15 16:17:16 +00:00
|
|
|
pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self {
|
|
|
|
self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
|
|
|
|
}
|
|
|
|
|
2022-07-20 21:43:37 -04:00
|
|
|
/// Provide a reference computed using a closure. The referee type
|
|
|
|
/// must be bounded by `'static`, but may be unsized.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Provides a reference to a field as a `&str`.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
/// # struct SomeConcreteType { business: String, party: String }
|
|
|
|
/// # fn today_is_a_weekday() -> bool { true }
|
|
|
|
///
|
|
|
|
/// impl Provider for SomeConcreteType {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// demand.provide_ref_with::<str>(|| {
|
|
|
|
/// if today_is_a_weekday() {
|
|
|
|
/// &self.business
|
|
|
|
/// } else {
|
|
|
|
/// &self.party
|
|
|
|
/// }
|
|
|
|
/// });
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
|
|
|
pub fn provide_ref_with<T: ?Sized + 'static>(
|
|
|
|
&mut self,
|
|
|
|
fulfil: impl FnOnce() -> &'a T,
|
|
|
|
) -> &mut Self {
|
|
|
|
self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
|
|
|
|
}
|
|
|
|
|
2021-12-15 16:17:16 +00:00
|
|
|
/// Provide a value with the given `Type` tag.
|
|
|
|
fn provide<I>(&mut self, value: I::Reified) -> &mut Self
|
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
|
|
|
|
res.0 = Some(value);
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work.
|
2022-06-13 09:29:55 +01:00
|
|
|
fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
|
2021-12-15 16:17:16 +00:00
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
|
|
|
|
res.0 = Some(fulfil());
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
2022-07-21 21:39:20 -04:00
|
|
|
|
|
|
|
/// Check if the `Demand` would be satisfied if provided with a
|
|
|
|
/// value of the specified type. If the type does not match or has
|
|
|
|
/// already been provided, returns false.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Check if an `u8` still needs to be provided and then provides
|
|
|
|
/// it.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
///
|
|
|
|
/// struct Parent(Option<u8>);
|
|
|
|
///
|
|
|
|
/// impl Provider for Parent {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// if let Some(v) = self.0 {
|
|
|
|
/// demand.provide_value::<u8>(v);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// struct Child {
|
|
|
|
/// parent: Parent,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl Child {
|
|
|
|
/// // Pretend that this takes a lot of resources to evaluate.
|
|
|
|
/// fn an_expensive_computation(&self) -> Option<u8> {
|
|
|
|
/// Some(99)
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl Provider for Child {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// // In general, we don't know if this call will provide
|
|
|
|
/// // an `u8` value or not...
|
|
|
|
/// self.parent.provide(demand);
|
|
|
|
///
|
|
|
|
/// // ...so we check to see if the `u8` is needed before
|
|
|
|
/// // we run our expensive computation.
|
|
|
|
/// if demand.would_be_satisfied_by_value_of::<u8>() {
|
|
|
|
/// if let Some(v) = self.an_expensive_computation() {
|
|
|
|
/// demand.provide_value::<u8>(v);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // The demand will be satisfied now, regardless of if
|
|
|
|
/// // the parent provided the value or we did.
|
|
|
|
/// assert!(!demand.would_be_satisfied_by_value_of::<u8>());
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// let parent = Parent(Some(42));
|
|
|
|
/// let child = Child { parent };
|
|
|
|
/// assert_eq!(Some(42), std::any::request_value::<u8>(&child));
|
|
|
|
///
|
|
|
|
/// let parent = Parent(None);
|
|
|
|
/// let child = Child { parent };
|
|
|
|
/// assert_eq!(Some(99), std::any::request_value::<u8>(&child));
|
|
|
|
/// ```
|
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
|
|
|
pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
|
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
|
|
|
self.would_be_satisfied_by::<tags::Value<T>>()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if the `Demand` would be satisfied if provided with a
|
|
|
|
/// reference to a value of the specified type. If the type does
|
|
|
|
/// not match or has already been provided, returns false.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// Check if a `&str` still needs to be provided and then provides
|
|
|
|
/// it.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #![feature(provide_any)]
|
|
|
|
///
|
|
|
|
/// use std::any::{Provider, Demand};
|
|
|
|
///
|
|
|
|
/// struct Parent(Option<String>);
|
|
|
|
///
|
|
|
|
/// impl Provider for Parent {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// if let Some(v) = &self.0 {
|
|
|
|
/// demand.provide_ref::<str>(v);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// struct Child {
|
|
|
|
/// parent: Parent,
|
|
|
|
/// name: String,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl Child {
|
|
|
|
/// // Pretend that this takes a lot of resources to evaluate.
|
|
|
|
/// fn an_expensive_computation(&self) -> Option<&str> {
|
|
|
|
/// Some(&self.name)
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl Provider for Child {
|
|
|
|
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
|
|
|
/// // In general, we don't know if this call will provide
|
|
|
|
/// // a `str` reference or not...
|
|
|
|
/// self.parent.provide(demand);
|
|
|
|
///
|
|
|
|
/// // ...so we check to see if the `&str` is needed before
|
|
|
|
/// // we run our expensive computation.
|
|
|
|
/// if demand.would_be_satisfied_by_ref_of::<str>() {
|
|
|
|
/// if let Some(v) = self.an_expensive_computation() {
|
|
|
|
/// demand.provide_ref::<str>(v);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // The demand will be satisfied now, regardless of if
|
|
|
|
/// // the parent provided the reference or we did.
|
|
|
|
/// assert!(!demand.would_be_satisfied_by_ref_of::<str>());
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// let parent = Parent(Some("parent".into()));
|
|
|
|
/// let child = Child { parent, name: "child".into() };
|
|
|
|
/// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child));
|
|
|
|
///
|
|
|
|
/// let parent = Parent(None);
|
|
|
|
/// let child = Child { parent, name: "child".into() };
|
|
|
|
/// assert_eq!(Some("child"), std::any::request_ref::<str>(&child));
|
|
|
|
/// ```
|
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
|
|
|
pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
|
|
|
|
where
|
|
|
|
T: ?Sized + 'static,
|
|
|
|
{
|
|
|
|
self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn would_be_satisfied_by<I>(&self) -> bool
|
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
|
|
|
|
}
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
|
2022-05-11 10:12:22 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
|
|
|
impl<'a> fmt::Debug for Demand<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("Demand").finish_non_exhaustive()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-15 16:17:16 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Type tags
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
mod tags {
|
|
|
|
//! Type tags are used to identify a type using a separate value. This module includes type tags
|
|
|
|
//! for some very common types.
|
|
|
|
//!
|
2022-05-11 10:12:22 +01:00
|
|
|
//! Currently type tags are not exposed to the user. But in the future, if you want to use the
|
|
|
|
//! Provider API with more complex types (typically those including lifetime parameters), you
|
|
|
|
//! will need to write your own tags.
|
2021-12-15 16:17:16 +00:00
|
|
|
|
|
|
|
use crate::marker::PhantomData;
|
|
|
|
|
|
|
|
/// This trait is implemented by specific tag types in order to allow
|
|
|
|
/// describing a type which can be requested for a given lifetime `'a`.
|
|
|
|
///
|
|
|
|
/// A few example implementations for type-driven tags can be found in this
|
|
|
|
/// module, although crates may also implement their own tags for more
|
|
|
|
/// complex types with internal lifetimes.
|
|
|
|
pub trait Type<'a>: Sized + 'static {
|
|
|
|
/// The type of values which may be tagged by this tag for the given
|
|
|
|
/// lifetime.
|
|
|
|
type Reified: 'a;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a
|
2022-05-11 10:12:22 +01:00
|
|
|
/// `?Sized` bound). E.g., `str`.
|
2021-12-15 16:17:16 +00:00
|
|
|
pub trait MaybeSizedType<'a>: Sized + 'static {
|
|
|
|
type Reified: 'a + ?Sized;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: Type<'a>> MaybeSizedType<'a> for T {
|
|
|
|
type Reified = T::Reified;
|
|
|
|
}
|
|
|
|
|
2022-04-12 10:49:53 +01:00
|
|
|
/// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements.
|
2021-12-15 16:17:16 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Value<T: 'static>(PhantomData<T>);
|
|
|
|
|
|
|
|
impl<'a, T: 'static> Type<'a> for Value<T> {
|
|
|
|
type Reified = T;
|
|
|
|
}
|
|
|
|
|
2022-06-10 20:53:49 -07:00
|
|
|
/// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound).
|
2021-12-15 16:17:16 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>);
|
|
|
|
|
|
|
|
impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> {
|
|
|
|
type Reified = T;
|
|
|
|
}
|
|
|
|
|
2022-05-11 10:12:22 +01:00
|
|
|
/// Type-based tag for reference types (`&'a T`, where T is represented by
|
|
|
|
/// `<I as MaybeSizedType<'a>>::Reified`.
|
2021-12-15 16:17:16 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Ref<I>(PhantomData<I>);
|
|
|
|
|
|
|
|
impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> {
|
|
|
|
type Reified = &'a I::Reified;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An `Option` with a type tag `I`.
|
|
|
|
///
|
|
|
|
/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed
|
|
|
|
/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically
|
|
|
|
/// checked for the concrete type, there is some degree of type safety.
|
|
|
|
#[repr(transparent)]
|
|
|
|
struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>);
|
|
|
|
|
|
|
|
impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
|
|
|
|
fn as_demand(&mut self) -> &mut Demand<'a> {
|
2022-05-11 10:12:22 +01:00
|
|
|
Demand::new(self as &mut (dyn Erased<'a> + 'a))
|
2021-12-15 16:17:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Represents a type-erased but identifiable object.
|
|
|
|
///
|
|
|
|
/// This trait is exclusively implemented by the `TaggedOption` type.
|
2022-05-11 10:12:22 +01:00
|
|
|
unsafe trait Erased<'a>: 'a {
|
2021-12-15 16:17:16 +00:00
|
|
|
/// The `TypeId` of the erased type.
|
|
|
|
fn tag_id(&self) -> TypeId;
|
|
|
|
}
|
|
|
|
|
2022-05-11 10:12:22 +01:00
|
|
|
unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {
|
2021-12-15 16:17:16 +00:00
|
|
|
fn tag_id(&self) -> TypeId {
|
|
|
|
TypeId::of::<I>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-14 07:56:09 +01:00
|
|
|
#[unstable(feature = "provide_any", issue = "96024")]
|
2022-05-11 10:12:22 +01:00
|
|
|
impl<'a> dyn Erased<'a> + 'a {
|
2021-12-15 16:17:16 +00:00
|
|
|
/// Returns some reference to the dynamic value if it is tagged with `I`,
|
2022-04-12 10:49:53 +01:00
|
|
|
/// or `None` otherwise.
|
2021-12-15 16:17:16 +00:00
|
|
|
#[inline]
|
2022-07-21 21:39:20 -04:00
|
|
|
fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
|
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
if self.tag_id() == TypeId::of::<I>() {
|
|
|
|
// SAFETY: Just checked whether we're pointing to an I.
|
|
|
|
Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns some mutable reference to the dynamic value if it is tagged with `I`,
|
|
|
|
/// or `None` otherwise.
|
|
|
|
#[inline]
|
2021-12-15 16:17:16 +00:00
|
|
|
fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
|
|
|
|
where
|
|
|
|
I: tags::Type<'a>,
|
|
|
|
{
|
|
|
|
if self.tag_id() == TypeId::of::<I>() {
|
|
|
|
// SAFETY: Just checked whether we're pointing to an I.
|
2022-05-11 10:12:22 +01:00
|
|
|
Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() })
|
2021-12-15 16:17:16 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|