Skip to content

Commit fd1d9c5

Browse files
authored
Unrolled build for #146886
Rollup merge of #146886 - taiki-e:rc-inner-align, r=Mark-Simulacrum Add repr(align(2)) to RcInner and ArcInner `Rc` currently assumes that `RcInner` has at least 2-byte alignment, but on AVR, `usize` has 1-byte alignment (this is because the AVR has 1-byte register sizes, so having 2-byte alignment is generally useless), breaking this assumption. https://github.com/rust-lang/rust/blob/9f32ccf35fb877270bc44a86a126440f04d676d0/library/alloc/src/rc.rs#L3005-L3008 This PR adds `repr(align(2))` to force `RcInner` to always have at least 2-byte alignment. Note that `ArcInner` doesn't need `repr(align(2))` because atomic types have the alignment same as its size. This PR adds a comment about this.
2 parents 42d009c + 9e79fac commit fd1d9c5

File tree

2 files changed

+12
-8
lines changed

2 files changed

+12
-8
lines changed

library/alloc/src/rc.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,9 @@ use crate::vec::Vec;
277277
// This is repr(C) to future-proof against possible field-reordering, which
278278
// would interfere with otherwise safe [into|from]_raw() of transmutable
279279
// inner types.
280-
#[repr(C)]
280+
// repr(align(2)) (forcing alignment to at least 2) is required because usize
281+
// has 1-byte alignment on AVR.
282+
#[repr(C, align(2))]
281283
struct RcInner<T: ?Sized> {
282284
strong: Cell<usize>,
283285
weak: Cell<usize>,

library/alloc/src/sync.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ pub struct Weak<
341341
// but it is not necessarily a valid pointer.
342342
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
343343
// to allocate space on the heap. That's not a value a real pointer
344-
// will ever have because RcInner has alignment at least 2.
344+
// will ever have because ArcInner has alignment at least 2.
345345
ptr: NonNull<ArcInner<T>>,
346346
alloc: A,
347347
}
@@ -366,7 +366,9 @@ impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
366366
// This is repr(C) to future-proof against possible field-reordering, which
367367
// would interfere with otherwise safe [into|from]_raw() of transmutable
368368
// inner types.
369-
#[repr(C)]
369+
// Unlike RcInner, repr(align(2)) is not strictly required because atomic types
370+
// have the alignment same as its size, but we use it for consistency and clarity.
371+
#[repr(C, align(2))]
370372
struct ArcInner<T: ?Sized> {
371373
strong: Atomic<usize>,
372374

@@ -1613,9 +1615,9 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
16131615
pub fn as_ptr(this: &Self) -> *const T {
16141616
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
16151617

1616-
// SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because
1618+
// SAFETY: This cannot go through Deref::deref or ArcInnerPtr::inner because
16171619
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
1618-
// write through the pointer after the Rc is recovered through `from_raw`.
1620+
// write through the pointer after the Arc is recovered through `from_raw`.
16191621
unsafe { &raw mut (*ptr).data }
16201622
}
16211623

@@ -2450,7 +2452,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
24502452
/// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then
24512453
/// they must not be dereferenced or have active borrows for the duration
24522454
/// of the returned borrow, and their inner type must be exactly the same as the
2453-
/// inner type of this Rc (including lifetimes). This is trivially the case if no
2455+
/// inner type of this Arc (including lifetimes). This is trivially the case if no
24542456
/// such pointers exist, for example immediately after `Arc::new`.
24552457
///
24562458
/// # Examples
@@ -3022,7 +3024,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
30223024
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
30233025
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
30243026
let offset = unsafe { data_offset(ptr) };
3025-
// Thus, we reverse the offset to get the whole RcInner.
3027+
// Thus, we reverse the offset to get the whole ArcInner.
30263028
// SAFETY: the pointer originated from a Weak, so this offset is safe.
30273029
unsafe { ptr.byte_sub(offset) as *mut ArcInner<T> }
30283030
};
@@ -4015,7 +4017,7 @@ impl<T: ?Sized, A: Allocator> Unpin for Arc<T, A> {}
40154017
/// valid instance of T, but the T is allowed to be dropped.
40164018
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
40174019
// Align the unsized value to the end of the ArcInner.
4018-
// Because RcInner is repr(C), it will always be the last field in memory.
4020+
// Because ArcInner is repr(C), it will always be the last field in memory.
40194021
// SAFETY: since the only unsized types possible are slices, trait objects,
40204022
// and extern types, the input safety requirement is currently enough to
40214023
// satisfy the requirements of align_of_val_raw; this is an implementation

0 commit comments

Comments
 (0)