Skip to content

Commit 6629010

Browse files
committed
Address reviewer comments
Signed-off-by: Nick Cameron <[email protected]>
1 parent 843f90c commit 6629010

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

library/core/src/any.rs

+37-18
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@
9393
//! trait for objects which can provide data, and the [`request_value`] and [`request_ref`]
9494
//! functions for requesting data from an object which implements `Provider`. Generally, end users
9595
//! 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.
9799
//!
98100
//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will
99101
//! request data from a trait object by specifying the type of the data.
@@ -155,7 +157,6 @@
155157

156158
use crate::fmt;
157159
use crate::intrinsics;
158-
use crate::mem::transmute;
159160

160161
///////////////////////////////////////////////////////////////////////////////
161162
// Any trait
@@ -781,18 +782,24 @@ pub trait Provider {
781782
/// Data providers should implement this method to provide *all* values they are able to
782783
/// provide by using `demand`.
783784
///
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+
///
784789
/// # Examples
785790
///
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`.
787793
///
788794
/// ```rust
789795
/// # #![feature(provide_any)]
790796
/// use std::any::{Provider, Demand};
791-
/// # struct SomeConcreteType { field: String }
797+
/// # struct SomeConcreteType { field: String, num_field: i32 }
792798
///
793799
/// impl Provider for SomeConcreteType {
794800
/// 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);
796803
/// }
797804
/// }
798805
/// ```
@@ -864,12 +871,18 @@ where
864871
/// A helper object for providing data by type.
865872
///
866873
/// A data provider provides values by calling this type's provide methods.
867-
#[allow(missing_debug_implementations)]
868874
#[unstable(feature = "provide_any", issue = "96024")]
869875
#[repr(transparent)]
870876
pub struct Demand<'a>(dyn Erased<'a> + 'a);
871877

872878
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+
873886
/// Provide a value or other type with only static lifetimes.
874887
///
875888
/// # Examples
@@ -943,6 +956,13 @@ impl<'a> Demand<'a> {
943956
}
944957
}
945958

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+
946966
///////////////////////////////////////////////////////////////////////////////
947967
// Type tags
948968
///////////////////////////////////////////////////////////////////////////////
@@ -951,9 +971,9 @@ mod tags {
951971
//! Type tags are used to identify a type using a separate value. This module includes type tags
952972
//! for some very common types.
953973
//!
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.
957977
958978
use crate::marker::PhantomData;
959979

@@ -970,7 +990,7 @@ mod tags {
970990
}
971991

972992
/// 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`.
974994
pub trait MaybeSizedType<'a>: Sized + 'static {
975995
type Reified: 'a + ?Sized;
976996
}
@@ -995,7 +1015,8 @@ mod tags {
9951015
type Reified = T;
9961016
}
9971017

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`.
9991020
#[derive(Debug)]
10001021
pub struct Ref<I>(PhantomData<I>);
10011022

@@ -1014,28 +1035,26 @@ struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>);
10141035

10151036
impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
10161037
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))
10201039
}
10211040
}
10221041

10231042
/// Represents a type-erased but identifiable object.
10241043
///
10251044
/// This trait is exclusively implemented by the `TaggedOption` type.
1026-
trait Erased<'a>: 'a {
1045+
unsafe trait Erased<'a>: 'a {
10271046
/// The `TypeId` of the erased type.
10281047
fn tag_id(&self) -> TypeId;
10291048
}
10301049

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> {
10321051
fn tag_id(&self) -> TypeId {
10331052
TypeId::of::<I>()
10341053
}
10351054
}
10361055

10371056
#[unstable(feature = "provide_any", issue = "96024")]
1038-
impl<'a> dyn Erased<'a> {
1057+
impl<'a> dyn Erased<'a> + 'a {
10391058
/// Returns some reference to the dynamic value if it is tagged with `I`,
10401059
/// or `None` otherwise.
10411060
#[inline]
@@ -1045,7 +1064,7 @@ impl<'a> dyn Erased<'a> {
10451064
{
10461065
if self.tag_id() == TypeId::of::<I>() {
10471066
// 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>>() })
10491068
} else {
10501069
None
10511070
}

0 commit comments

Comments
 (0)