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