Skip to content

Commit

Permalink
feat!: reduce size of Id and add IdRef
Browse files Browse the repository at this point in the history
This reduces the size of `Id` from 24 bytes to 16 bytes on 64-bit
systems, and from 12 bytes to 8 bytes in 32-bit systems.

It also adds an `IdRef` type that we can use instead of a `&Id`, this
avoids a double indirection (`&str` vs `&String`). In
`trustfall-rustdoc-adapter` we see a [7% perf improvement][1] when using
`&IdRef` instead of `&Id`.

Sadly, AFAIK, there is no way to safely coerce `Id(Box<str>)` to
`&IdRef(str)` so we need to do an unsafe
`std::mem::transmute(&str) -> &IdRef`.

[1]: obi1kenobi/trustfall-rustdoc-adapter#423 (comment)
  • Loading branch information
jalil-salame committed Aug 29, 2024
1 parent 569b327 commit 5bca39e
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ pub enum TypeBindingKind {
Constraint(Vec<GenericBound>),
}

#[doc(hidden)]
#[repr(transparent)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct IdType<T: ?Sized>(T);

/// An opaque identifier for an item.
///
/// It can be used to lookup in [`Crate::index`] or [`Crate::paths`] to resolve it
Expand All @@ -296,11 +301,28 @@ pub enum TypeBindingKind {
/// Rustdoc makes no guarantees about the inner value of Id's. Applications
/// should treat them as opaque keys to lookup items, and avoid attempting
/// to parse them, or otherwise depend on any implementation details.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
// FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types.
pub struct Id(pub String);
pub type Id = IdType<Box<str>>;

/// A reference to an [`Id`]
pub type IdRef = IdType<str>;

impl std::ops::Deref for Id {
type Target = IdRef;

fn deref(&self) -> &Self::Target {
let inner: &str = self.0.as_ref();
// Safety: &IdRef has the same layout and lifetime as &str due to the repr(transparent)
unsafe { std::mem::transmute(inner) }
}
}

impl std::borrow::Borrow<IdRef> for Id {
fn borrow(&self) -> &IdRef {
self
}
}

/// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any aditional info.
/// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any additional info.
///
/// Part of [`ItemSummary`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
Expand Down

0 comments on commit 5bca39e

Please sign in to comment.