Rollup merge of #99583 - shepmaster:provider-plus-plus, r=yaahc
Add additional methods to the Demand type This adds on to the original tracking issue #96024 r? `````@yaahc`````
This commit is contained in:
commit
0e82dc969f
2 changed files with 234 additions and 7 deletions
|
@ -796,7 +796,7 @@ pub trait Provider {
|
|||
/// impl Provider for SomeConcreteType {
|
||||
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
||||
/// demand.provide_ref::<str>(&self.field)
|
||||
/// .provide_value::<i32>(|| self.num_field);
|
||||
/// .provide_value::<i32>(self.num_field);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -881,28 +881,55 @@ impl<'a> Demand<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// Provides a `String` by cloning.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![feature(provide_any)]
|
||||
/// #![feature(provide_any)]
|
||||
///
|
||||
/// use std::any::{Provider, Demand};
|
||||
/// # struct SomeConcreteType { field: String }
|
||||
///
|
||||
/// impl Provider for SomeConcreteType {
|
||||
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
|
||||
/// demand.provide_value::<String>(|| self.field.clone());
|
||||
/// demand.provide_value_with::<String>(|| self.field.clone());
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "provide_any", issue = "96024")]
|
||||
pub fn provide_value<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
|
||||
pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.provide_with::<tags::Value<T>>(fulfil)
|
||||
}
|
||||
|
||||
/// Provide a reference, note that the referee type must be bounded by `'static`,
|
||||
/// Provide a reference. The referee type must be bounded by `'static`,
|
||||
/// but may be unsized.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -910,7 +937,8 @@ impl<'a> Demand<'a> {
|
|||
/// Provides a reference to a field as a `&str`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![feature(provide_any)]
|
||||
/// #![feature(provide_any)]
|
||||
///
|
||||
/// use std::any::{Provider, Demand};
|
||||
/// # struct SomeConcreteType { field: String }
|
||||
///
|
||||
|
@ -925,6 +953,40 @@ impl<'a> Demand<'a> {
|
|||
self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// Provide a value with the given `Type` tag.
|
||||
fn provide<I>(&mut self, value: I::Reified) -> &mut Self
|
||||
where
|
||||
|
@ -946,6 +1008,156 @@ impl<'a> Demand<'a> {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// 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)))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "provide_any", issue = "96024")]
|
||||
|
@ -1050,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a {
|
|||
/// Returns some reference to the dynamic value if it is tagged with `I`,
|
||||
/// or `None` otherwise.
|
||||
#[inline]
|
||||
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]
|
||||
fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
|
||||
where
|
||||
I: tags::Type<'a>,
|
||||
|
|
|
@ -142,7 +142,7 @@ impl Provider for SomeConcreteType {
|
|||
demand
|
||||
.provide_ref::<String>(&self.some_string)
|
||||
.provide_ref::<str>(&self.some_string)
|
||||
.provide_value::<String>(|| "bye".to_owned());
|
||||
.provide_value_with::<String>(|| "bye".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue