Skip to content

Commit 2d677c8

Browse files
authored
Rollup merge of rust-lang#99583 - shepmaster:provider-plus-plus, r=yaahc
Add additional methods to the Demand type This adds on to the original tracking issue rust-lang#96024 r? ``@yaahc``
2 parents b10aed0 + 260ec93 commit 2d677c8

File tree

2 files changed

+234
-7
lines changed

2 files changed

+234
-7
lines changed

library/core/src/any.rs

+233-6
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ pub trait Provider {
796796
/// impl Provider for SomeConcreteType {
797797
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
798798
/// demand.provide_ref::<str>(&self.field)
799-
/// .provide_value::<i32>(|| self.num_field);
799+
/// .provide_value::<i32>(self.num_field);
800800
/// }
801801
/// }
802802
/// ```
@@ -881,36 +881,64 @@ impl<'a> Demand<'a> {
881881
///
882882
/// # Examples
883883
///
884+
/// Provides an `u8`.
885+
///
886+
/// ```rust
887+
/// #![feature(provide_any)]
888+
///
889+
/// use std::any::{Provider, Demand};
890+
/// # struct SomeConcreteType { field: u8 }
891+
///
892+
/// impl Provider for SomeConcreteType {
893+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
894+
/// demand.provide_value::<u8>(self.field);
895+
/// }
896+
/// }
897+
/// ```
898+
#[unstable(feature = "provide_any", issue = "96024")]
899+
pub fn provide_value<T>(&mut self, value: T) -> &mut Self
900+
where
901+
T: 'static,
902+
{
903+
self.provide::<tags::Value<T>>(value)
904+
}
905+
906+
/// Provide a value or other type with only static lifetimes computed using a closure.
907+
///
908+
/// # Examples
909+
///
884910
/// Provides a `String` by cloning.
885911
///
886912
/// ```rust
887-
/// # #![feature(provide_any)]
913+
/// #![feature(provide_any)]
914+
///
888915
/// use std::any::{Provider, Demand};
889916
/// # struct SomeConcreteType { field: String }
890917
///
891918
/// impl Provider for SomeConcreteType {
892919
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
893-
/// demand.provide_value::<String>(|| self.field.clone());
920+
/// demand.provide_value_with::<String>(|| self.field.clone());
894921
/// }
895922
/// }
896923
/// ```
897924
#[unstable(feature = "provide_any", issue = "96024")]
898-
pub fn provide_value<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
925+
pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
899926
where
900927
T: 'static,
901928
{
902929
self.provide_with::<tags::Value<T>>(fulfil)
903930
}
904931

905-
/// Provide a reference, note that the referee type must be bounded by `'static`,
932+
/// Provide a reference. The referee type must be bounded by `'static`,
906933
/// but may be unsized.
907934
///
908935
/// # Examples
909936
///
910937
/// Provides a reference to a field as a `&str`.
911938
///
912939
/// ```rust
913-
/// # #![feature(provide_any)]
940+
/// #![feature(provide_any)]
941+
///
914942
/// use std::any::{Provider, Demand};
915943
/// # struct SomeConcreteType { field: String }
916944
///
@@ -925,6 +953,40 @@ impl<'a> Demand<'a> {
925953
self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
926954
}
927955

956+
/// Provide a reference computed using a closure. The referee type
957+
/// must be bounded by `'static`, but may be unsized.
958+
///
959+
/// # Examples
960+
///
961+
/// Provides a reference to a field as a `&str`.
962+
///
963+
/// ```rust
964+
/// #![feature(provide_any)]
965+
///
966+
/// use std::any::{Provider, Demand};
967+
/// # struct SomeConcreteType { business: String, party: String }
968+
/// # fn today_is_a_weekday() -> bool { true }
969+
///
970+
/// impl Provider for SomeConcreteType {
971+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
972+
/// demand.provide_ref_with::<str>(|| {
973+
/// if today_is_a_weekday() {
974+
/// &self.business
975+
/// } else {
976+
/// &self.party
977+
/// }
978+
/// });
979+
/// }
980+
/// }
981+
/// ```
982+
#[unstable(feature = "provide_any", issue = "96024")]
983+
pub fn provide_ref_with<T: ?Sized + 'static>(
984+
&mut self,
985+
fulfil: impl FnOnce() -> &'a T,
986+
) -> &mut Self {
987+
self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
988+
}
989+
928990
/// Provide a value with the given `Type` tag.
929991
fn provide<I>(&mut self, value: I::Reified) -> &mut Self
930992
where
@@ -946,6 +1008,156 @@ impl<'a> Demand<'a> {
9461008
}
9471009
self
9481010
}
1011+
1012+
/// Check if the `Demand` would be satisfied if provided with a
1013+
/// value of the specified type. If the type does not match or has
1014+
/// already been provided, returns false.
1015+
///
1016+
/// # Examples
1017+
///
1018+
/// Check if an `u8` still needs to be provided and then provides
1019+
/// it.
1020+
///
1021+
/// ```rust
1022+
/// #![feature(provide_any)]
1023+
///
1024+
/// use std::any::{Provider, Demand};
1025+
///
1026+
/// struct Parent(Option<u8>);
1027+
///
1028+
/// impl Provider for Parent {
1029+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
1030+
/// if let Some(v) = self.0 {
1031+
/// demand.provide_value::<u8>(v);
1032+
/// }
1033+
/// }
1034+
/// }
1035+
///
1036+
/// struct Child {
1037+
/// parent: Parent,
1038+
/// }
1039+
///
1040+
/// impl Child {
1041+
/// // Pretend that this takes a lot of resources to evaluate.
1042+
/// fn an_expensive_computation(&self) -> Option<u8> {
1043+
/// Some(99)
1044+
/// }
1045+
/// }
1046+
///
1047+
/// impl Provider for Child {
1048+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
1049+
/// // In general, we don't know if this call will provide
1050+
/// // an `u8` value or not...
1051+
/// self.parent.provide(demand);
1052+
///
1053+
/// // ...so we check to see if the `u8` is needed before
1054+
/// // we run our expensive computation.
1055+
/// if demand.would_be_satisfied_by_value_of::<u8>() {
1056+
/// if let Some(v) = self.an_expensive_computation() {
1057+
/// demand.provide_value::<u8>(v);
1058+
/// }
1059+
/// }
1060+
///
1061+
/// // The demand will be satisfied now, regardless of if
1062+
/// // the parent provided the value or we did.
1063+
/// assert!(!demand.would_be_satisfied_by_value_of::<u8>());
1064+
/// }
1065+
/// }
1066+
///
1067+
/// let parent = Parent(Some(42));
1068+
/// let child = Child { parent };
1069+
/// assert_eq!(Some(42), std::any::request_value::<u8>(&child));
1070+
///
1071+
/// let parent = Parent(None);
1072+
/// let child = Child { parent };
1073+
/// assert_eq!(Some(99), std::any::request_value::<u8>(&child));
1074+
/// ```
1075+
#[unstable(feature = "provide_any", issue = "96024")]
1076+
pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
1077+
where
1078+
T: 'static,
1079+
{
1080+
self.would_be_satisfied_by::<tags::Value<T>>()
1081+
}
1082+
1083+
/// Check if the `Demand` would be satisfied if provided with a
1084+
/// reference to a value of the specified type. If the type does
1085+
/// not match or has already been provided, returns false.
1086+
///
1087+
/// # Examples
1088+
///
1089+
/// Check if a `&str` still needs to be provided and then provides
1090+
/// it.
1091+
///
1092+
/// ```rust
1093+
/// #![feature(provide_any)]
1094+
///
1095+
/// use std::any::{Provider, Demand};
1096+
///
1097+
/// struct Parent(Option<String>);
1098+
///
1099+
/// impl Provider for Parent {
1100+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
1101+
/// if let Some(v) = &self.0 {
1102+
/// demand.provide_ref::<str>(v);
1103+
/// }
1104+
/// }
1105+
/// }
1106+
///
1107+
/// struct Child {
1108+
/// parent: Parent,
1109+
/// name: String,
1110+
/// }
1111+
///
1112+
/// impl Child {
1113+
/// // Pretend that this takes a lot of resources to evaluate.
1114+
/// fn an_expensive_computation(&self) -> Option<&str> {
1115+
/// Some(&self.name)
1116+
/// }
1117+
/// }
1118+
///
1119+
/// impl Provider for Child {
1120+
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
1121+
/// // In general, we don't know if this call will provide
1122+
/// // a `str` reference or not...
1123+
/// self.parent.provide(demand);
1124+
///
1125+
/// // ...so we check to see if the `&str` is needed before
1126+
/// // we run our expensive computation.
1127+
/// if demand.would_be_satisfied_by_ref_of::<str>() {
1128+
/// if let Some(v) = self.an_expensive_computation() {
1129+
/// demand.provide_ref::<str>(v);
1130+
/// }
1131+
/// }
1132+
///
1133+
/// // The demand will be satisfied now, regardless of if
1134+
/// // the parent provided the reference or we did.
1135+
/// assert!(!demand.would_be_satisfied_by_ref_of::<str>());
1136+
/// }
1137+
/// }
1138+
///
1139+
/// let parent = Parent(Some("parent".into()));
1140+
/// let child = Child { parent, name: "child".into() };
1141+
/// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child));
1142+
///
1143+
/// let parent = Parent(None);
1144+
/// let child = Child { parent, name: "child".into() };
1145+
/// assert_eq!(Some("child"), std::any::request_ref::<str>(&child));
1146+
/// ```
1147+
#[unstable(feature = "provide_any", issue = "96024")]
1148+
pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
1149+
where
1150+
T: ?Sized + 'static,
1151+
{
1152+
self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
1153+
}
1154+
1155+
fn would_be_satisfied_by<I>(&self) -> bool
1156+
where
1157+
I: tags::Type<'a>,
1158+
{
1159+
matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
1160+
}
9491161
}
9501162

9511163
#[unstable(feature = "provide_any", issue = "96024")]
@@ -1050,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a {
10501262
/// Returns some reference to the dynamic value if it is tagged with `I`,
10511263
/// or `None` otherwise.
10521264
#[inline]
1265+
fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
1266+
where
1267+
I: tags::Type<'a>,
1268+
{
1269+
if self.tag_id() == TypeId::of::<I>() {
1270+
// SAFETY: Just checked whether we're pointing to an I.
1271+
Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
1272+
} else {
1273+
None
1274+
}
1275+
}
1276+
1277+
/// Returns some mutable reference to the dynamic value if it is tagged with `I`,
1278+
/// or `None` otherwise.
1279+
#[inline]
10531280
fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
10541281
where
10551282
I: tags::Type<'a>,

library/core/tests/any.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl Provider for SomeConcreteType {
142142
demand
143143
.provide_ref::<String>(&self.some_string)
144144
.provide_ref::<str>(&self.some_string)
145-
.provide_value::<String>(|| "bye".to_owned());
145+
.provide_value_with::<String>(|| "bye".to_owned());
146146
}
147147
}
148148

0 commit comments

Comments
 (0)