1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-07-26 23:10:56 +00:00

Compare commits

...

2 commits

Author SHA1 Message Date
N.E.C. 04c45f2a4e
Merge bd626e9a95 into 85f4c3f095 2025-07-13 01:07:18 +00:00
N.E.C. bd626e9a95 Revert "Improve codegen when accessing BorrowedNPC fields"
This reverts commit 738cff69fe.

A user in the rust-lang forum noted that a BorrowedNPC in the Unborrowed
state could be exposed if a panic occurs.
2025-07-12 18:05:29 -07:00

View file

@ -36,50 +36,25 @@ pub enum BorrowedNPC<'a> {
cell: &'a NPCCell, cell: &'a NPCCell,
token: &'a mut NPCAccessToken, token: &'a mut NPCAccessToken,
}, },
/// SAFETY: Constructing the `Unborrowed` variant is **inherently unsafe**.
/// Rust doesn't support marking enum variants as unsafe, but if it did, this
/// one would be.
///
/// A `BorrowedNPC` in the `Unborrowed` state must **never** be dereferenced.
/// Doing so will invoke `unreachable_unchecked`, leading to immediate Undefined
/// Behavior.
///
/// Never expose a `BorrowedNPC` in the `Unborrowed` state outside this module.
Unborrowed, Unborrowed,
} }
impl BorrowedNPC<'_> {
unsafe fn new_unborrowed() -> Self {
Self::Unborrowed
}
}
impl Deref for BorrowedNPC<'_> { impl Deref for BorrowedNPC<'_> {
type Target = NPC; type Target = NPC;
#[inline]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
BorrowedNPC::Borrowed { ref_mut, .. } => &*ref_mut, BorrowedNPC::Borrowed { ref_mut, .. } => &*ref_mut,
// `unreachable_unchecked` tells the compiler to assume this branch _ => unreachable!()
// will never be reached, skipping any checks.
// Verified via Godbolt: This significantly improves codegen when
// accessing `BorrowedNPC` fields.
_ => unsafe { core::hint::unreachable_unchecked() }
} }
} }
} }
impl DerefMut for BorrowedNPC<'_> { impl DerefMut for BorrowedNPC<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
match self { match self {
BorrowedNPC::Borrowed { ref_mut, .. } => &mut *ref_mut, BorrowedNPC::Borrowed { ref_mut, .. } => &mut *ref_mut,
// `unreachable_unchecked` tells the compiler to assume this branch _ => unreachable!()
// will never be reached, skipping any checks.
// Verified via Godbolt: This significantly improves codegen when
// accessing `BorrowedNPC` fields.
_ => unsafe { core::hint::unreachable_unchecked() }
} }
} }
} }
@ -91,10 +66,10 @@ impl TokenProvider for BorrowedNPC<'_> {
{ {
match self { match self {
BorrowedNPC::Borrowed { .. } => { BorrowedNPC::Borrowed { .. } => {
let old = std::mem::replace(self, unsafe { BorrowedNPC::new_unborrowed() }); let old = std::mem::replace(self, BorrowedNPC::Unborrowed);
let (old_ref_mut, token, cell) = match old { let (old_ref_mut, token, cell) = match old {
BorrowedNPC::Borrowed { ref_mut, token, cell } => (ref_mut, token, cell), BorrowedNPC::Borrowed { ref_mut, token, cell } => (ref_mut, token, cell),
_ => unsafe { core::hint::unreachable_unchecked() } _ => unreachable!()
}; };
drop(old_ref_mut); drop(old_ref_mut);
@ -105,7 +80,7 @@ impl TokenProvider for BorrowedNPC<'_> {
result result
} }
_ => unsafe { core::hint::unreachable_unchecked() } _ => unreachable!()
} }
} }
} }