Skip to content

Commit

Permalink
[Unalign::update] Optimize when T is unaligned (#1703)
Browse files Browse the repository at this point in the history
Closes #1702
  • Loading branch information
joshlf authored Sep 20, 2024
1 parent 15fa71b commit 76fd0f9
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,21 @@ impl<T> Unalign<T> {
/// [`T: Unaligned`]: Unaligned
#[inline]
pub fn update<O, F: FnOnce(&mut T) -> O>(&mut self, f: F) -> O {
if mem::align_of::<T>() == 1 {
// While we advise callers to use `DerefMut` when `T: Unaligned`,
// not all callers will be able to guarantee `T: Unaligned` in all
// cases. In particular, callers who are themselves providing an API
// which is generic over `T` may sometimes be called by *their*
// callers with `T` such that `align_of::<T>() == 1`, but cannot
// guarantee this in the general case. Thus, this optimization may
// sometimes be helpful.

// SAFETY: Since `T`'s alignment is 1, `self` satisfies its
// alignment by definition.
let t = unsafe { self.deref_mut_unchecked() };
return f(t);
}

// On drop, this moves `copy` out of itself and uses `ptr::write` to
// overwrite `slf`.
struct WriteBackOnDrop<T> {
Expand Down Expand Up @@ -535,6 +550,11 @@ mod tests {
}));
assert!(res.is_err());
assert_eq!(u.into_inner(), Box::new(AU64(124)));

// Test the align_of::<T>() == 1 optimization.
let mut u = Unalign::new([0u8, 1]);
u.update(|a| a[0] += 1);
assert_eq!(u.get(), [1u8, 1]);
}

#[test]
Expand Down

0 comments on commit 76fd0f9

Please sign in to comment.