7
7
// those terms.
8
8
9
9
use core:: {
10
+ cell:: UnsafeCell ,
10
11
mem:: { self , ManuallyDrop , MaybeUninit } ,
11
12
num:: { NonZeroUsize , Wrapping } ,
12
13
ptr:: NonNull ,
14
+ sync:: atomic:: {
15
+ AtomicBool , AtomicI16 , AtomicI32 , AtomicI8 , AtomicIsize , AtomicPtr , AtomicU16 , AtomicU32 ,
16
+ AtomicU8 , AtomicUsize ,
17
+ } ,
13
18
} ;
14
19
15
20
use crate :: {
@@ -21,11 +26,11 @@ use crate::{
21
26
///
22
27
/// # Safety
23
28
///
24
- /// `T: TransparentWrapper` implies that `T` has the same size and field offsets
25
- /// as [`T::Inner`]. Note that this implies that `T` has [`UnsafeCell`]s
26
- /// covering the same byte ranges as `T::Inner`. This further implies that `T `
27
- /// has zero-sized `UnsafeCell`s (e.g., `UnsafeCell<()>`, `[UnsafeCell<u8>; 0] `,
28
- /// etc) at the same byte offsets as `T::Inner`.
29
+ /// `T: TransparentWrapper` implies that:
30
+ /// - `T` has the same size as [`T::Inner`]
31
+ /// - `T` has `UnsafeCell`s covering the same byte ranges as `T::Inner`
32
+ /// - `T` has zero-sized `UnsafeCell`s (e.g., `UnsafeCell<()>`,
33
+ /// `[UnsafeCell<u8>; 0]`, etc) at the same byte offsets as `T::Inner`
29
34
///
30
35
/// Further, `T: TransparentWrapper<I>` implies that:
31
36
/// - If a `T` pointer satisfies the alignment invariant `I::Alignment`, then
@@ -100,22 +105,21 @@ impl<I: invariant::Validity> ValidityVariance<I> for Invariant {
100
105
}
101
106
102
107
// SAFETY:
103
- // - Per [1], `MaybeUninit<T>` has the same layout as `Inner = T`.
104
- // - Per [2], `MaybeUninit<T>` has `UnsafeCell`s at the same byte ranges as
108
+ // - Per [1], `MaybeUninit<T>` has `UnsafeCell`s at the same byte ranges as
105
109
// `Inner = T`, and `UnsafeCell`s at the same byte offsets as `T`.
106
110
// - See inline comments for other safety justifications.
107
111
//
108
- // [1] Per https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1:
109
- //
110
- // `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as
111
- // `T`.
112
- //
113
- // [2] TODO(#896): Write a safety proof before the next stable release.
112
+ // [1] TODO(#896): Write a safety proof before the next stable release.
114
113
unsafe impl < T , I : Invariants > TransparentWrapper < I > for MaybeUninit < T > {
115
114
type Inner = T ;
116
115
117
- // SAFETY: Per [1] (from comment above), `MaybeUninit<T>` has the same
118
- // layout as `T`, and thus has the same alignment as `T`.
116
+ // SAFETY: Per [1], `MaybeUninit<T>` has the same layout as `T`, and thus
117
+ // has the same alignment as `T`.
118
+ //
119
+ // [1] Per https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1:
120
+ //
121
+ // `MaybeUninit<T>` is guaranteed to have the same size, alignment, and
122
+ // ABI as `T`.
119
123
type AlignmentVariance = Covariant ;
120
124
// SAFETY: `MaybeUninit` has no validity invariants. Thus, a valid
121
125
// `MaybeUninit<T>` is not necessarily a valid `T`.
@@ -139,22 +143,21 @@ unsafe impl<T, I: Invariants> TransparentWrapper<I> for MaybeUninit<T> {
139
143
}
140
144
141
145
// SAFETY:
142
- // - Per [1], `ManuallyDrop<T>` has the same layout as `Inner = T`.
143
- // - Per [2], `ManuallyDrop<T>` has `UnsafeCell`s at the same byte ranges as
146
+ // - Per [1], `ManuallyDrop<T>` has `UnsafeCell`s at the same byte ranges as
144
147
// `Inner = T`, and `UnsafeCell`s at the same byte offsets as `T`.
145
148
// - See inline comments for other safety justifications.
146
149
//
147
- // [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:
148
- //
149
- // `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
150
- // `T`
151
- //
152
- // [2] TODO(#896): Write a safety proof before the next stable release.
150
+ // [1] TODO(#896): Write a safety proof before the next stable release.
153
151
unsafe impl < T : ?Sized , I : Invariants > TransparentWrapper < I > for ManuallyDrop < T > {
154
152
type Inner = T ;
155
153
156
- // SAFETY: Per [1] (from comment above), `ManuallyDrop<T>` has the same
157
- // layout as `T`, and thus has the same alignment as `T`.
154
+ // SAFETY: Per [1], `ManuallyDrop<T>` has the same layout as `T`, and thus
155
+ // has the same alignment as `T`.
156
+ //
157
+ // [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:
158
+ //
159
+ // `ManuallyDrop<T>` is guaranteed to have the same layout and bit
160
+ // validity as `T`
158
161
type AlignmentVariance = Covariant ;
159
162
160
163
// SAFETY: Per [1] (from comment above), `ManuallyDrop<T>` has the same bit
@@ -181,21 +184,20 @@ unsafe impl<T: ?Sized, I: Invariants> TransparentWrapper<I> for ManuallyDrop<T>
181
184
}
182
185
183
186
// SAFETY:
184
- // - Per [1], `Wrapping<T>` has the same layout as `Inner = T`.
185
- // - Per [2], `Wrapping<T>` has `UnsafeCell`s at the same byte ranges as `Inner
187
+ // - Per [1], `Wrapping<T>` has `UnsafeCell`s at the same byte ranges as `Inner
186
188
// = T`, and `UnsafeCell`s at the same byte offsets as `T`.
187
189
// - See inline comments for other safety justifications.
188
190
//
189
- // [1] Per https://doc.rust-lang.org/core/num/struct.Wrapping.html#layout-1:
190
- //
191
- // `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
192
- //
193
- // [2] TODO(#896): Write a safety proof before the next stable release.
191
+ // [1] TODO(#896): Write a safety proof before the next stable release.
194
192
unsafe impl < T , I : Invariants > TransparentWrapper < I > for Wrapping < T > {
195
193
type Inner = T ;
196
194
197
- // SAFETY: Per [1] (from comment above), `Wrapping<T>` has the same layout
198
- // as `T`, and thus has the same alignment as `T`.
195
+ // SAFETY: Per [1], `Wrapping<T>` has the same layout as `T`, and thus has
196
+ // the same alignment as `T`.
197
+ //
198
+ // [1] Per https://doc.rust-lang.org/core/num/struct.Wrapping.html#layout-1:
199
+ //
200
+ // `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
199
201
type AlignmentVariance = Covariant ;
200
202
201
203
// SAFETY: `Wrapping<T>` has only one field, which is `pub` [2]. We are also
@@ -230,9 +232,8 @@ unsafe impl<T, I: Invariants> TransparentWrapper<I> for Wrapping<T> {
230
232
}
231
233
232
234
// SAFETY: We define `Unalign<T>` to be a `#[repr(C, packed)]` type wrapping a
233
- // single `T` field. Thus, `Unalign<T>` has the same size and field offsets as
234
- // `T`, has `UnsafeCell`s at the same byte ranges as `T`, and has `UnsafeCell`s
235
- // at the same byte offsets as `T`.
235
+ // single `T` field. Thus, `Unalign<T>` has `UnsafeCell`s at the same byte
236
+ // ranges as `T` and has `UnsafeCell`s at the same byte offsets as `T`.
236
237
//
237
238
// See inline comments for other safety justifications.
238
239
unsafe impl < T , I : Invariants > TransparentWrapper < I > for Unalign < T > {
@@ -248,22 +249,124 @@ unsafe impl<T, I: Invariants> TransparentWrapper<I> for Unalign<T> {
248
249
type ValidityVariance = Covariant ;
249
250
250
251
fn cast_into_inner ( ptr : * mut Unalign < T > ) -> * mut T {
251
- // SAFETY: Per the comment above, `Unalign<T>` has the same layout as
252
- // `T`. Thus, this cast preserves size.
252
+ // SAFETY: We define `Unalign<T>` to be a `#[repr(C, packed)]` wrapper
253
+ // around a single `T` field. Thus, `Unalign<T>` has the size as `T`.
254
+ // Thus, this cast preserves size.
253
255
//
254
256
// This cast trivially preserves provenance.
255
257
ptr. cast :: < T > ( )
256
258
}
257
259
258
260
fn cast_from_inner ( ptr : * mut T ) -> * mut Unalign < T > {
259
- // SAFETY: Per the comment above , `Unalign<T>` has the same layout as
260
- // `T`. Thus, this cast preserves size.
261
+ // SAFETY: Per the comment in `cast_into_inner` , `Unalign<T>` has the
262
+ // same size as `T`. Thus, this cast preserves size.
261
263
//
262
264
// This cast trivially preserves provenance.
263
265
ptr. cast :: < Unalign < T > > ( )
264
266
}
265
267
}
266
268
269
+ /// Implements `TransparentWrapper` for an atomic type.
270
+ ///
271
+ /// # Safety
272
+ ///
273
+ /// The caller promises that `$atomic` is an atomic type whose natie equivalent
274
+ /// is `$native`.
275
+ macro_rules! unsafe_impl_transparent_wrapper_for_atomic {
276
+ ( $( #[ $attr: meta] ) * $( , ) ?) => { } ;
277
+ ( $( #[ $attr: meta] ) * $atomic: ty [ $native: ty] , $( $atomics: ty [ $natives: ty] ) ,* $( , ) ?) => {
278
+ $( #[ $attr] ) *
279
+ // SAFETY: See safety comment in next match arm.
280
+ unsafe impl <I : Invariants > TransparentWrapper <I > for $atomic {
281
+ unsafe_impl_transparent_wrapper_for_atomic!( @inner $atomic [ $native] ) ;
282
+ }
283
+ unsafe_impl_transparent_wrapper_for_atomic!( $( #[ $attr] ) * $( $atomics [ $natives] , ) * ) ;
284
+ } ;
285
+ ( $( #[ $attr: meta] ) * $tyvar: ident => $atomic: ty [ $native: ty] ) => {
286
+ // The caller has promised that `$atomic` and `$native` are an atomic
287
+ // type and its native counterpart, respectively. It is "obvious" that
288
+ // each atomic type contains a single `UnsafeCell` that covers all bytes
289
+ // of the type, but we can also prove it:
290
+ // - Since `$atomic` provides an API which permits loading and storing
291
+ // values of type `$native` via a `&self` (shared) reference, *some*
292
+ // interior mutation must be happening, and interior mutation can only
293
+ // happen via `UnsafeCell`. Further, there must be enough bytes in
294
+ // `$atomic` covered by an `UnsafeCell` to hold every possible value
295
+ // of `$native`.
296
+ // - Per [1], `$atomic` has the same size as `$native`. This on its own
297
+ // isn't enough: it would still be possible for `$atomic` to store
298
+ // `$native` using a compact representation (for `$native` types for
299
+ // which some bit patterns are illegal). However, this is ruled out by
300
+ // the fact that `$atomic` has the same bit validity as `$native` [1].
301
+ // Thus, we can conclude that every byte of `$atomic` must be covered
302
+ // by an `UnsafeCell`.
303
+ //
304
+ // Thus, every byte of `$atomic` is covered by an `UnsafeCell`, and we
305
+ // set `type Inner = UnsafeCell<$native>`. Thus, `Self` and
306
+ // `Self::Inner` have `UnsafeCell`s covering the same byte ranges.
307
+ //
308
+ // See inline comments for safety requirements regarding invariant
309
+ // variance.
310
+ //
311
+ // [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
312
+ // Cite docs once they've landed.
313
+ $( #[ $attr] ) *
314
+ unsafe impl <$tyvar, I : Invariants > TransparentWrapper <I > for $atomic {
315
+ unsafe_impl_transparent_wrapper_for_atomic!( @inner $atomic [ $native] ) ;
316
+ }
317
+ } ;
318
+ ( @inner $atomic: ty [ $native: ty] ) => {
319
+ type Inner = UnsafeCell <$native>;
320
+
321
+ // SAFETY: No safety justification is required for an invariant
322
+ // variance.
323
+ type AlignmentVariance = Invariant ;
324
+
325
+ // SAFETY: Per [1], all atomic types have the same bit validity as their
326
+ // native counterparts. The caller has promised that `$atomic` and
327
+ // `$native` are an atomic type and its native counterpart,
328
+ // respectively.
329
+ //
330
+ // [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
331
+ // Cite docs once they've landed.
332
+ type ValidityVariance = Covariant ;
333
+
334
+ fn cast_into_inner( ptr: * mut $atomic) -> * mut UnsafeCell <$native> {
335
+ // SAFETY: Per [1] (from comment on impl block), `$atomic` has the
336
+ // same size as `$native`. Thus, this cast preserves size.
337
+ //
338
+ // This cast trivially preserves provenance.
339
+ ptr. cast:: <UnsafeCell <$native>>( )
340
+ }
341
+
342
+ fn cast_from_inner( ptr: * mut UnsafeCell <$native>) -> * mut $atomic {
343
+ // SAFETY: Per [1] (from comment on impl block), `$atomic` has the
344
+ // same size as `$native`. Thus, this cast preserves size.
345
+ //
346
+ // This cast trivially preserves provenance.
347
+ ptr. cast:: <$atomic>( )
348
+ }
349
+ } ;
350
+ }
351
+
352
+ safety_comment ! {
353
+ /// SAFETY:
354
+ /// All of these pass an atomic type and that type's native equivalent, as
355
+ /// required by the macro safety preconditions.
356
+ unsafe_impl_transparent_wrapper_for_atomic!( T => AtomicPtr <T > [ * mut T ] ) ;
357
+ unsafe_impl_transparent_wrapper_for_atomic!(
358
+ AtomicBool [ bool ] ,
359
+ AtomicI16 [ i16 ] , AtomicI32 [ i32 ] , AtomicI8 [ i8 ] , AtomicIsize [ isize ] ,
360
+ AtomicU16 [ u16 ] , AtomicU32 [ u32 ] , AtomicU8 [ u8 ] , AtomicUsize [ usize ] ,
361
+ ) ;
362
+ #[ cfg( not( target_arch = "powerpc" ) ) ]
363
+ unsafe_impl_transparent_wrapper_for_atomic!(
364
+ #[ cfg_attr( doc_cfg, doc( cfg( not( target_arch = "powerpc" ) ) ) ) ]
365
+ core:: sync:: atomic:: AtomicI64 [ i64 ] ,
366
+ core:: sync:: atomic:: AtomicU64 [ u64 ] ,
367
+ ) ;
368
+ }
369
+
267
370
pub ( crate ) trait AsAddress {
268
371
fn addr ( self ) -> usize ;
269
372
}
0 commit comments