Skip to content

Commit

Permalink
Support eager and lazy methods for providing references and values
Browse files Browse the repository at this point in the history
There are times where computing a value may be cheap, or where
computing a reference may be expensive, so this fills out the
possibilities.
  • Loading branch information
shepmaster committed Aug 23, 2022
1 parent 1cff564 commit 38de102
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 7 deletions.
74 changes: 68 additions & 6 deletions library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
/// }
/// }
/// ```
Expand Down Expand Up @@ -881,36 +881,64 @@ 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
///
/// 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 }
///
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion library/core/tests/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}

Expand Down

0 comments on commit 38de102

Please sign in to comment.