93
93
//! trait for objects which can provide data, and the [`request_value`] and [`request_ref`]
94
94
//! functions for requesting data from an object which implements `Provider`. Generally, end users
95
95
//! should not call `request_*` directly, they are helper functions for intermediate implementers
96
- //! to use to implement a user-facing interface.
96
+ //! to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is
97
+ //! safety concern here; intermediate implementers can typically support methods rather than
98
+ //! free functions and use more specific names.
97
99
//!
98
100
//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will
99
101
//! request data from a trait object by specifying the type of the data.
155
157
156
158
use crate :: fmt;
157
159
use crate :: intrinsics;
158
- use crate :: mem:: transmute;
159
160
160
161
///////////////////////////////////////////////////////////////////////////////
161
162
// Any trait
@@ -781,18 +782,24 @@ pub trait Provider {
781
782
/// Data providers should implement this method to provide *all* values they are able to
782
783
/// provide by using `demand`.
783
784
///
785
+ /// Note that the `provide_*` methods on `Demand` have short-circuit semantics: if an earlier
786
+ /// method has successfully provided a value, then later methods will not get an opportunity to
787
+ /// provide.
788
+ ///
784
789
/// # Examples
785
790
///
786
- /// Provides a reference to a field with type `String` as a `&str`.
791
+ /// Provides a reference to a field with type `String` as a `&str`, and a value of
792
+ /// type `i32`.
787
793
///
788
794
/// ```rust
789
795
/// # #![feature(provide_any)]
790
796
/// use std::any::{Provider, Demand};
791
- /// # struct SomeConcreteType { field: String }
797
+ /// # struct SomeConcreteType { field: String, num_field: i32 }
792
798
///
793
799
/// impl Provider for SomeConcreteType {
794
800
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
795
- /// demand.provide_ref::<str>(&self.field);
801
+ /// demand.provide_ref::<str>(&self.field)
802
+ /// .provide_value::<i32, _>(|| self.num_field);
796
803
/// }
797
804
/// }
798
805
/// ```
@@ -864,12 +871,18 @@ where
864
871
/// A helper object for providing data by type.
865
872
///
866
873
/// A data provider provides values by calling this type's provide methods.
867
- #[ allow( missing_debug_implementations) ]
868
874
#[ unstable( feature = "provide_any" , issue = "96024" ) ]
869
875
#[ repr( transparent) ]
870
876
pub struct Demand < ' a > ( dyn Erased < ' a > + ' a ) ;
871
877
872
878
impl < ' a > Demand < ' a > {
879
+ /// Create a new `&mut Demand` from a `&mut dyn Erased` trait object.
880
+ fn new < ' b > ( erased : & ' b mut ( dyn Erased < ' a > + ' a ) ) -> & ' b mut Demand < ' a > {
881
+ // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since
882
+ // `Demand` is repr(transparent).
883
+ unsafe { & mut * ( erased as * mut dyn Erased < ' a > as * mut Demand < ' a > ) }
884
+ }
885
+
873
886
/// Provide a value or other type with only static lifetimes.
874
887
///
875
888
/// # Examples
@@ -943,6 +956,13 @@ impl<'a> Demand<'a> {
943
956
}
944
957
}
945
958
959
+ #[ unstable( feature = "provide_any" , issue = "96024" ) ]
960
+ impl < ' a > fmt:: Debug for Demand < ' a > {
961
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
962
+ f. debug_struct ( "Demand" ) . finish_non_exhaustive ( )
963
+ }
964
+ }
965
+
946
966
///////////////////////////////////////////////////////////////////////////////
947
967
// Type tags
948
968
///////////////////////////////////////////////////////////////////////////////
@@ -951,9 +971,9 @@ mod tags {
951
971
//! Type tags are used to identify a type using a separate value. This module includes type tags
952
972
//! for some very common types.
953
973
//!
954
- //! Many users of the provider APIs will not need to use type tags at all. But if you want to
955
- //! use them with more complex types (typically those including lifetime parameters), you will
956
- //! need to write your own tags.
974
+ //! Currently type tags are not exposed to the user. But in the future, if you want to use the
975
+ //! Provider API with more complex types (typically those including lifetime parameters), you
976
+ //! will need to write your own tags.
957
977
958
978
use crate :: marker:: PhantomData ;
959
979
@@ -970,7 +990,7 @@ mod tags {
970
990
}
971
991
972
992
/// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a
973
- /// `' Sized` bound). E.g., `str`.
993
+ /// `? Sized` bound). E.g., `str`.
974
994
pub trait MaybeSizedType < ' a > : Sized + ' static {
975
995
type Reified : ' a + ?Sized ;
976
996
}
@@ -995,7 +1015,8 @@ mod tags {
995
1015
type Reified = T ;
996
1016
}
997
1017
998
- /// Type-based tag for `&'a T` types.
1018
+ /// Type-based tag for reference types (`&'a T`, where T is represented by
1019
+ /// `<I as MaybeSizedType<'a>>::Reified`.
999
1020
#[ derive( Debug ) ]
1000
1021
pub struct Ref < I > ( PhantomData < I > ) ;
1001
1022
@@ -1014,28 +1035,26 @@ struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>);
1014
1035
1015
1036
impl < ' a , I : tags:: Type < ' a > > TaggedOption < ' a , I > {
1016
1037
fn as_demand ( & mut self ) -> & mut Demand < ' a > {
1017
- // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since
1018
- // `Demand` is repr(transparent) and holds only a `dyn Erased<'a> + 'a`.
1019
- unsafe { transmute ( self as & mut ( dyn Erased < ' a > + ' a ) ) }
1038
+ Demand :: new ( self as & mut ( dyn Erased < ' a > + ' a ) )
1020
1039
}
1021
1040
}
1022
1041
1023
1042
/// Represents a type-erased but identifiable object.
1024
1043
///
1025
1044
/// This trait is exclusively implemented by the `TaggedOption` type.
1026
- trait Erased < ' a > : ' a {
1045
+ unsafe trait Erased < ' a > : ' a {
1027
1046
/// The `TypeId` of the erased type.
1028
1047
fn tag_id ( & self ) -> TypeId ;
1029
1048
}
1030
1049
1031
- impl < ' a , I : tags:: Type < ' a > > Erased < ' a > for TaggedOption < ' a , I > {
1050
+ unsafe impl < ' a , I : tags:: Type < ' a > > Erased < ' a > for TaggedOption < ' a , I > {
1032
1051
fn tag_id ( & self ) -> TypeId {
1033
1052
TypeId :: of :: < I > ( )
1034
1053
}
1035
1054
}
1036
1055
1037
1056
#[ unstable( feature = "provide_any" , issue = "96024" ) ]
1038
- impl < ' a > dyn Erased < ' a > {
1057
+ impl < ' a > dyn Erased < ' a > + ' a {
1039
1058
/// Returns some reference to the dynamic value if it is tagged with `I`,
1040
1059
/// or `None` otherwise.
1041
1060
#[ inline]
@@ -1045,7 +1064,7 @@ impl<'a> dyn Erased<'a> {
1045
1064
{
1046
1065
if self . tag_id ( ) == TypeId :: of :: < I > ( ) {
1047
1066
// SAFETY: Just checked whether we're pointing to an I.
1048
- Some ( unsafe { & mut * ( self as * mut Self as * mut TaggedOption < ' a , I > ) } )
1067
+ Some ( unsafe { & mut * ( self as * mut Self ) . cast :: < TaggedOption < ' a , I > > ( ) } )
1049
1068
} else {
1050
1069
None
1051
1070
}
0 commit comments