@@ -1057,6 +1057,30 @@ safety_comment! {
1057
1057
#[ cfg_attr( doc_cfg, doc( cfg( feature = "derive" ) ) ) ]
1058
1058
pub use zerocopy_derive:: FromZeroes ;
1059
1059
1060
+ /// Types which do not contain any [`UnsafeCell`]s.
1061
+ ///
1062
+ /// WARNING: Do not implement this trait yourself! Instead, use
1063
+ /// `#[derive(NoCell)]`.
1064
+ ///
1065
+ /// # Safety
1066
+ ///
1067
+ /// If a type implements `NoCell`, unsafe code may assume that that type does
1068
+ /// not contain any [`UnsafeCell`]s and does not contain any types which contain
1069
+ /// any [`UnsafeCell`]s transitively. If a type implements `NoCell` which
1070
+ /// violates this assumption, it may cause [undefined behavior].
1071
+ ///
1072
+ /// [`UnsafeCell`]: core::cell::UnsafeCell
1073
+ /// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
1074
+ #[ doc( hidden) ]
1075
+ pub unsafe trait NoCell {
1076
+ // The `Self: Sized` bound makes it so that `NoCell` is still object
1077
+ // safe.
1078
+ #[ doc( hidden) ]
1079
+ fn only_derive_is_allowed_to_implement_this_trait ( )
1080
+ where
1081
+ Self : Sized ;
1082
+ }
1083
+
1060
1084
/// Types whose validity can be checked at runtime, allowing them to be
1061
1085
/// conditionally converted from byte slices.
1062
1086
///
@@ -2127,18 +2151,20 @@ safety_comment! {
2127
2151
/// SAFETY:
2128
2152
/// Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a
2129
2153
/// zero-sized type to have a size of 0 and an alignment of 1."
2154
+ /// - `NoCell`: `()` self-evidently does not contain any `UnsafeCell`s.
2130
2155
/// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`: There
2131
2156
/// is only one possible sequence of 0 bytes, and `()` is inhabited.
2132
2157
/// - `AsBytes`: Since `()` has size 0, it contains no padding bytes.
2133
2158
/// - `Unaligned`: `()` has alignment 1.
2134
2159
///
2135
2160
/// [1] https://doc.rust-lang.org/reference/type-layout.html#tuple-layout
2136
- unsafe_impl!( ( ) : TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2161
+ unsafe_impl!( ( ) : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2137
2162
assert_unaligned!( ( ) ) ;
2138
2163
}
2139
2164
2140
2165
safety_comment ! {
2141
2166
/// SAFETY:
2167
+ /// - `NoCell`: These types self-evidently do not contain any `UnsafeCell`s.
2142
2168
/// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`: all bit
2143
2169
/// patterns are valid for numeric types [1]
2144
2170
/// - `AsBytes`: numeric types have no padding bytes [1]
@@ -2171,25 +2197,26 @@ safety_comment! {
2171
2197
/// TODO(#278): Once we've updated the trait docs to refer to `u8`s rather
2172
2198
/// than bits or bytes, update this comment, especially the reference to
2173
2199
/// [1].
2174
- unsafe_impl!( u8 : TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2175
- unsafe_impl!( i8 : TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2200
+ unsafe_impl!( u8 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2201
+ unsafe_impl!( i8 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2176
2202
assert_unaligned!( u8 , i8 ) ;
2177
- unsafe_impl!( u16 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2178
- unsafe_impl!( i16 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2179
- unsafe_impl!( u32 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2180
- unsafe_impl!( i32 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2181
- unsafe_impl!( u64 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2182
- unsafe_impl!( i64 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2183
- unsafe_impl!( u128 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2184
- unsafe_impl!( i128 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2185
- unsafe_impl!( usize : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2186
- unsafe_impl!( isize : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2187
- unsafe_impl!( f32 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2188
- unsafe_impl!( f64 : TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2203
+ unsafe_impl!( u16 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2204
+ unsafe_impl!( i16 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2205
+ unsafe_impl!( u32 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2206
+ unsafe_impl!( i32 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2207
+ unsafe_impl!( u64 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2208
+ unsafe_impl!( i64 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2209
+ unsafe_impl!( u128 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2210
+ unsafe_impl!( i128 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2211
+ unsafe_impl!( usize : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2212
+ unsafe_impl!( isize : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2213
+ unsafe_impl!( f32 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2214
+ unsafe_impl!( f64 : NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ;
2189
2215
}
2190
2216
2191
2217
safety_comment ! {
2192
2218
/// SAFETY:
2219
+ /// - `NoCell`: `bool` self-evidently does not contain any `UnsafeCell`s.
2193
2220
/// - `FromZeroes`: Valid since "[t]he value false has the bit pattern
2194
2221
/// 0x00" [1].
2195
2222
/// - `AsBytes`: Since "the boolean type has a size and alignment of 1 each"
@@ -2200,7 +2227,7 @@ safety_comment! {
2200
2227
/// has a size and alignment of 1 each."
2201
2228
///
2202
2229
/// [1] https://doc.rust-lang.org/reference/types/boolean.html
2203
- unsafe_impl!( bool : FromZeroes , AsBytes , Unaligned ) ;
2230
+ unsafe_impl!( bool : NoCell , FromZeroes , AsBytes , Unaligned ) ;
2204
2231
assert_unaligned!( bool ) ;
2205
2232
/// SAFETY:
2206
2233
/// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
@@ -2243,6 +2270,7 @@ safety_comment! {
2243
2270
}
2244
2271
safety_comment ! {
2245
2272
/// SAFETY:
2273
+ /// - `NoCell`: `char` self-evidently does not contain any `UnsafeCell`s.
2246
2274
/// - `FromZeroes`: Per reference [1], "[a] value of type char is a Unicode
2247
2275
/// scalar value (i.e. a code point that is not a surrogate), represented
2248
2276
/// as a 32-bit unsigned word in the 0x0000 to 0xD7FF or 0xE000 to
@@ -2252,7 +2280,7 @@ safety_comment! {
2252
2280
/// all bit patterns are valid for `char`.
2253
2281
///
2254
2282
/// [1] https://doc.rust-lang.org/reference/types/textual.html
2255
- unsafe_impl!( char : FromZeroes , AsBytes ) ;
2283
+ unsafe_impl!( char : NoCell , FromZeroes , AsBytes ) ;
2256
2284
/// SAFETY:
2257
2285
/// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
2258
2286
/// closure:
@@ -2289,14 +2317,18 @@ safety_comment! {
2289
2317
}
2290
2318
safety_comment ! {
2291
2319
/// SAFETY:
2292
- /// - `FromZeroes`, `AsBytes`, `Unaligned`: Per the reference [1], `str`
2293
- /// has the same layout as `[u8]`, and `[u8]` is `FromZeroes`, `AsBytes`,
2294
- /// and `Unaligned`.
2320
+ /// Per the Reference [1], `str` has the same layout as `[u8]`.
2321
+ /// - `NoCell`: `[u8]` does not contain any `UnsafeCell`s.
2322
+ /// - `FromZeroes`, `AsBytes`, `Unaligned`: `[u8]` is `FromZeroes`,
2323
+ /// `AsBytes`, and `Unaligned`.
2295
2324
///
2296
2325
/// Note that we don't `assert_unaligned!(str)` because `assert_unaligned!`
2297
2326
/// uses `align_of`, which only works for `Sized` types.
2298
2327
///
2299
- /// TODO(#429): Add quotes from documentation.
2328
+ /// TODO(#429):
2329
+ /// - Add quotes from documentation.
2330
+ /// - Improve safety proof for `FromZeroes` and `AsBytes`; having the same
2331
+ /// layout as `[u8]` isn't sufficient.
2300
2332
///
2301
2333
/// [1] https://doc.rust-lang.org/reference/type-layout.html#str-layout
2302
2334
unsafe_impl!( str : FromZeroes , AsBytes , Unaligned ) ;
@@ -2333,6 +2365,7 @@ safety_comment! {
2333
2365
// `NonZeroXxx` is `AsBytes`, but not `FromZeroes` or `FromBytes`.
2334
2366
//
2335
2367
/// SAFETY:
2368
+ /// - `NoCell`: TODO
2336
2369
/// - `AsBytes`: `NonZeroXxx` has the same layout as its associated
2337
2370
/// primitive. Since it is the same size, this guarantees it has no
2338
2371
/// padding - integers have no padding, and there's no room for padding
@@ -2353,19 +2386,19 @@ safety_comment! {
2353
2386
/// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html
2354
2387
/// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
2355
2388
/// that layout is the same as primitive layout.
2356
- unsafe_impl!( NonZeroU8 : AsBytes , Unaligned ) ;
2357
- unsafe_impl!( NonZeroI8 : AsBytes , Unaligned ) ;
2389
+ unsafe_impl!( NonZeroU8 : NoCell , AsBytes , Unaligned ) ;
2390
+ unsafe_impl!( NonZeroI8 : NoCell , AsBytes , Unaligned ) ;
2358
2391
assert_unaligned!( NonZeroU8 , NonZeroI8 ) ;
2359
- unsafe_impl!( NonZeroU16 : AsBytes ) ;
2360
- unsafe_impl!( NonZeroI16 : AsBytes ) ;
2361
- unsafe_impl!( NonZeroU32 : AsBytes ) ;
2362
- unsafe_impl!( NonZeroI32 : AsBytes ) ;
2363
- unsafe_impl!( NonZeroU64 : AsBytes ) ;
2364
- unsafe_impl!( NonZeroI64 : AsBytes ) ;
2365
- unsafe_impl!( NonZeroU128 : AsBytes ) ;
2366
- unsafe_impl!( NonZeroI128 : AsBytes ) ;
2367
- unsafe_impl!( NonZeroUsize : AsBytes ) ;
2368
- unsafe_impl!( NonZeroIsize : AsBytes ) ;
2392
+ unsafe_impl!( NonZeroU16 : NoCell , AsBytes ) ;
2393
+ unsafe_impl!( NonZeroI16 : NoCell , AsBytes ) ;
2394
+ unsafe_impl!( NonZeroU32 : NoCell , AsBytes ) ;
2395
+ unsafe_impl!( NonZeroI32 : NoCell , AsBytes ) ;
2396
+ unsafe_impl!( NonZeroU64 : NoCell , AsBytes ) ;
2397
+ unsafe_impl!( NonZeroI64 : NoCell , AsBytes ) ;
2398
+ unsafe_impl!( NonZeroU128 : NoCell , AsBytes ) ;
2399
+ unsafe_impl!( NonZeroI128 : NoCell , AsBytes ) ;
2400
+ unsafe_impl!( NonZeroUsize : NoCell , AsBytes ) ;
2401
+ unsafe_impl!( NonZeroIsize : NoCell , AsBytes ) ;
2369
2402
/// SAFETY:
2370
2403
/// - The safety requirements for `unsafe_impl!` with an `is_bit_valid`
2371
2404
/// closure:
@@ -2507,6 +2540,7 @@ safety_comment! {
2507
2540
/// that the `#[repr(transparent)]` attribute is "considered part of the
2508
2541
/// public ABI".
2509
2542
///
2543
+ /// - `NoCell`: TODO
2510
2544
/// - `TryFromBytes`: The safety requirements for `unsafe_impl!` with an
2511
2545
/// `is_bit_valid` closure:
2512
2546
/// - Given `t: *mut Wrapping<T>` and `let r = *mut T`, `r` refers to an
@@ -2542,6 +2576,7 @@ safety_comment! {
2542
2576
/// Reference this documentation once it's available on stable.
2543
2577
///
2544
2578
/// [2] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
2579
+ unsafe_impl!( T : NoCell => NoCell for Wrapping <T >) ;
2545
2580
unsafe_impl!( T : TryFromBytes => TryFromBytes for Wrapping <T >; |candidate: Ptr <T >| {
2546
2581
// SAFETY:
2547
2582
// - Since `T` and `Wrapping<T>` have the same layout and bit validity
@@ -2565,6 +2600,7 @@ safety_comment! {
2565
2600
// since it may contain uninitialized bytes.
2566
2601
//
2567
2602
/// SAFETY:
2603
+ /// - `NoCell`: TODO
2568
2604
/// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`:
2569
2605
/// `MaybeUninit<T>` has no restrictions on its contents. Unfortunately,
2570
2606
/// in addition to bit validity, `TryFromBytes`, `FromZeroes` and
@@ -2581,6 +2617,7 @@ safety_comment! {
2581
2617
/// `FromBytes` and `RefFromBytes`, or if we introduce a separate
2582
2618
/// `NoCell`/`Freeze` trait, we can relax the trait bounds for `FromZeroes`
2583
2619
/// and `FromBytes`.
2620
+ unsafe_impl!( T : NoCell => NoCell for MaybeUninit <T >) ;
2584
2621
unsafe_impl!( T : TryFromBytes => TryFromBytes for MaybeUninit <T >) ;
2585
2622
unsafe_impl!( T : FromZeroes => FromZeroes for MaybeUninit <T >) ;
2586
2623
unsafe_impl!( T : FromBytes => FromBytes for MaybeUninit <T >) ;
@@ -2593,6 +2630,7 @@ safety_comment! {
2593
2630
/// accessing the inner value is safe (meaning that it's unsound to leave
2594
2631
/// the inner value uninitialized while exposing the `ManuallyDrop` to safe
2595
2632
/// code).
2633
+ /// - `NoCell`: TODO
2596
2634
/// - `FromZeroes`, `FromBytes`: Since it has the same layout as `T`, any
2597
2635
/// valid `T` is a valid `ManuallyDrop<T>`. If `T: FromZeroes`, a sequence
2598
2636
/// of zero bytes is a valid `T`, and thus a valid `ManuallyDrop<T>`. If
@@ -2616,6 +2654,7 @@ safety_comment! {
2616
2654
/// - Once [1] (added in
2617
2655
/// https://github.com/rust-lang/rust/pull/115522) is available on stable,
2618
2656
/// quote the stable docs instead of the nightly docs.
2657
+ unsafe_impl!( T : ?Sized + NoCell => NoCell for ManuallyDrop <T >) ;
2619
2658
unsafe_impl!( T : ?Sized + FromZeroes => FromZeroes for ManuallyDrop <T >) ;
2620
2659
unsafe_impl!( T : ?Sized + FromBytes => FromBytes for ManuallyDrop <T >) ;
2621
2660
unsafe_impl!( T : ?Sized + AsBytes => AsBytes for ManuallyDrop <T >) ;
@@ -2637,26 +2676,29 @@ safety_comment! {
2637
2676
///
2638
2677
/// In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s
2639
2678
/// laid out back-to-back with no bytes in between. Therefore, `[T]` or `[T;
2640
- /// N]` are `FromZeroes`, `FromBytes`, and `AsBytes` if `T` is
2679
+ /// N]` are `NoCell`, ` FromZeroes`, `FromBytes`, and `AsBytes` if `T` is
2641
2680
/// (respectively). Furthermore, since an array/slice has "the same
2642
2681
/// alignment of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is.
2643
2682
///
2644
2683
/// Note that we don't `assert_unaligned!` for slice types because
2645
2684
/// `assert_unaligned!` uses `align_of`, which only works for `Sized` types.
2646
2685
///
2647
2686
/// [1] https://doc.rust-lang.org/reference/type-layout.html#array-layout
2687
+ unsafe_impl!( const N : usize , T : NoCell => NoCell for [ T ; N ] ) ;
2648
2688
unsafe_impl!( const N : usize , T : FromZeroes => FromZeroes for [ T ; N ] ) ;
2649
2689
unsafe_impl!( const N : usize , T : FromBytes => FromBytes for [ T ; N ] ) ;
2650
2690
unsafe_impl!( const N : usize , T : AsBytes => AsBytes for [ T ; N ] ) ;
2651
2691
unsafe_impl!( const N : usize , T : Unaligned => Unaligned for [ T ; N ] ) ;
2652
2692
assert_unaligned!( [ ( ) ; 0 ] , [ ( ) ; 1 ] , [ u8 ; 0 ] , [ u8 ; 1 ] ) ;
2693
+ unsafe_impl!( T : NoCell => NoCell for [ T ] ) ;
2653
2694
unsafe_impl!( T : FromZeroes => FromZeroes for [ T ] ) ;
2654
2695
unsafe_impl!( T : FromBytes => FromBytes for [ T ] ) ;
2655
2696
unsafe_impl!( T : AsBytes => AsBytes for [ T ] ) ;
2656
2697
unsafe_impl!( T : Unaligned => Unaligned for [ T ] ) ;
2657
2698
}
2658
2699
safety_comment ! {
2659
2700
/// SAFETY:
2701
+ /// - `NoCell`: TODO
2660
2702
/// - `FromZeroes`: For thin pointers (note that `T: Sized`), the zero
2661
2703
/// pointer is considered "null". [1] No operations which require
2662
2704
/// provenance are legal on null pointers, so this is not a footgun.
@@ -2668,9 +2710,17 @@ safety_comment! {
2668
2710
///
2669
2711
/// [1] TODO(https://github.com/rust-lang/rust/pull/116988): Cite the
2670
2712
/// documentation once this PR lands.
2713
+ unsafe_impl!( T => NoCell for * const T ) ;
2714
+ unsafe_impl!( T => NoCell for * mut T ) ;
2671
2715
unsafe_impl!( T => FromZeroes for * const T ) ;
2672
2716
unsafe_impl!( T => FromZeroes for * mut T ) ;
2673
2717
}
2718
+ safety_comment ! {
2719
+ /// SAFETY:
2720
+ /// TODO
2721
+ unsafe_impl!( T : ?Sized => NoCell for & ' _ T ) ;
2722
+ unsafe_impl!( T : ?Sized => NoCell for & ' _ mut T ) ;
2723
+ }
2674
2724
2675
2725
// SIMD support
2676
2726
//
@@ -2721,6 +2771,7 @@ safety_comment! {
2721
2771
// also `TryFromBytes`, `FromZeroes`, `FromBytes`, or `AsBytes` respectively.
2722
2772
// - Since no upper bound is placed on the alignment, no SIMD type can be
2723
2773
// guaranteed to be `Unaligned`.
2774
+ // - `NoCell`: TODO
2724
2775
//
2725
2776
// Also per [1]:
2726
2777
//
@@ -2761,7 +2812,7 @@ mod simd {
2761
2812
safety_comment! {
2762
2813
/// SAFETY:
2763
2814
/// See comment on module definition for justification.
2764
- $( unsafe_impl!( $typ: TryFromBytes , FromZeroes , FromBytes , AsBytes ) ; ) *
2815
+ $( unsafe_impl!( $typ: NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ; ) *
2765
2816
}
2766
2817
}
2767
2818
} ;
@@ -5344,6 +5395,7 @@ mod tests {
5344
5395
5345
5396
#[ test]
5346
5397
fn test_object_safety ( ) {
5398
+ fn _takes_no_cell ( _: & dyn NoCell ) { }
5347
5399
fn _takes_from_zeroes ( _: & dyn FromZeroes ) { }
5348
5400
fn _takes_from_bytes ( _: & dyn FromBytes ) { }
5349
5401
fn _takes_unaligned ( _: & dyn Unaligned ) { }
0 commit comments