Simplify provider api to improve llvm ir
This commit is contained in:
@@ -404,9 +404,9 @@ fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reifi
|
||||
where
|
||||
I: tags::Type<'a>,
|
||||
{
|
||||
let mut tagged = TaggedOption::<'a, I>(None);
|
||||
let mut tagged = Tagged { tag_id: TypeId::of::<I>(), value: TaggedOption::<'a, I>(None) };
|
||||
err.provide(tagged.as_request());
|
||||
tagged.0
|
||||
tagged.value.0
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -507,16 +507,9 @@ where
|
||||
///
|
||||
#[unstable(feature = "error_generic_member_access", issue = "99301")]
|
||||
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
|
||||
pub struct Request<'a>(dyn Erased<'a> + 'a);
|
||||
pub struct Request<'a>(Tagged<dyn Erased<'a> + 'a>);
|
||||
|
||||
impl<'a> Request<'a> {
|
||||
/// Create a new `&mut Request` from a `&mut dyn Erased` trait object.
|
||||
fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Request<'a> {
|
||||
// SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Request<'a>` is safe since
|
||||
// `Request` is repr(transparent).
|
||||
unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Request<'a>) }
|
||||
}
|
||||
|
||||
/// Provide a value or other type with only static lifetimes.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -940,27 +933,28 @@ pub(crate) mod tags {
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>);
|
||||
|
||||
impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
|
||||
impl<'a, I: tags::Type<'a>> Tagged<TaggedOption<'a, I>> {
|
||||
pub(crate) fn as_request(&mut self) -> &mut Request<'a> {
|
||||
Request::new(self as &mut (dyn Erased<'a> + 'a))
|
||||
let erased = self as &mut Tagged<dyn Erased<'a> + 'a>;
|
||||
// SAFETY: transmuting `&mut Tagged<dyn Erased<'a> + 'a>` to `&mut Request<'a>` is safe since
|
||||
// `Request` is repr(transparent).
|
||||
unsafe { &mut *(erased as *mut Tagged<dyn Erased<'a>> as *mut Request<'a>) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a type-erased but identifiable object.
|
||||
///
|
||||
/// This trait is exclusively implemented by the `TaggedOption` type.
|
||||
unsafe trait Erased<'a>: 'a {
|
||||
/// The `TypeId` of the erased type.
|
||||
fn tag_id(&self) -> TypeId;
|
||||
unsafe trait Erased<'a>: 'a {}
|
||||
|
||||
unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {}
|
||||
|
||||
struct Tagged<E: ?Sized> {
|
||||
tag_id: TypeId,
|
||||
value: E,
|
||||
}
|
||||
|
||||
unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {
|
||||
fn tag_id(&self) -> TypeId {
|
||||
TypeId::of::<I>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> dyn Erased<'a> + 'a {
|
||||
impl<'a> Tagged<dyn Erased<'a> + 'a> {
|
||||
/// Returns some reference to the dynamic value if it is tagged with `I`,
|
||||
/// or `None` otherwise.
|
||||
#[inline]
|
||||
@@ -968,9 +962,9 @@ impl<'a> dyn Erased<'a> + 'a {
|
||||
where
|
||||
I: tags::Type<'a>,
|
||||
{
|
||||
if self.tag_id() == TypeId::of::<I>() {
|
||||
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>>() })
|
||||
Some(&unsafe { &*(self as *const Self).cast::<Tagged<TaggedOption<'a, I>>>() }.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -983,9 +977,12 @@ impl<'a> dyn Erased<'a> + 'a {
|
||||
where
|
||||
I: tags::Type<'a>,
|
||||
{
|
||||
if self.tag_id() == TypeId::of::<I>() {
|
||||
// SAFETY: Just checked whether we're pointing to an I.
|
||||
Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() })
|
||||
if self.tag_id == TypeId::of::<I>() {
|
||||
Some(
|
||||
// SAFETY: Just checked whether we're pointing to an I.
|
||||
&mut unsafe { &mut *(self as *mut Self).cast::<Tagged<TaggedOption<'a, I>>>() }
|
||||
.value,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user