From 5bca39e616708e39b3f63cd5132c458f11016535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jalil=20David=20Salam=C3=A9=20Messina?= Date: Thu, 29 Aug 2024 20:45:52 +0200 Subject: [PATCH] feat!: reduce size of Id and add IdRef 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)` to `&IdRef(str)` so we need to do an unsafe `std::mem::transmute(&str) -> &IdRef`. [1]: https://github.com/obi1kenobi/trustfall-rustdoc-adapter/pull/423#issuecomment-2318526055 --- src/lib.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a785dd5..007caf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -285,6 +285,11 @@ pub enum TypeBindingKind { Constraint(Vec), } +#[doc(hidden)] +#[repr(transparent)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct IdType(T); + /// An opaque identifier for an item. /// /// It can be used to lookup in [`Crate::index`] or [`Crate::paths`] to resolve it @@ -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>; + +/// A reference to an [`Id`] +pub type IdRef = IdType; + +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 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)]