@@ -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:
@@ -2424,6 +2457,9 @@ safety_comment! {
2424
2457
///
2425
2458
/// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
2426
2459
/// for layout guarantees.
2460
+ ///
2461
+ /// TODO(#251): Implement `NoCell` (possibly by implementing it for
2462
+ /// `Option<T>` where `T: NoCell`).
2427
2463
unsafe_impl!( Option <NonZeroU8 >: TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2428
2464
unsafe_impl!( Option <NonZeroI8 >: TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
2429
2465
assert_unaligned!( Option <NonZeroU8 >, Option <NonZeroI8 >) ;
@@ -2507,6 +2543,8 @@ safety_comment! {
2507
2543
/// that the `#[repr(transparent)]` attribute is "considered part of the
2508
2544
/// public ABI".
2509
2545
///
2546
+ /// - `NoCell`: `Wrapping<T>` has `UnsafeCell`s exactly when `T` does, so
2547
+ /// `T: NoCell` guarantees that `Wrapping<T>` has no `UnsafeCell`s.
2510
2548
/// - `TryFromBytes`: The safety requirements for `unsafe_impl!` with an
2511
2549
/// `is_bit_valid` closure:
2512
2550
/// - Given `t: *mut Wrapping<T>` and `let r = *mut T`, `r` refers to an
@@ -2542,6 +2580,7 @@ safety_comment! {
2542
2580
/// Reference this documentation once it's available on stable.
2543
2581
///
2544
2582
/// [2] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
2583
+ unsafe_impl!( T : NoCell => NoCell for Wrapping <T >) ;
2545
2584
unsafe_impl!( T : TryFromBytes => TryFromBytes for Wrapping <T >; |candidate: Ptr <T >| {
2546
2585
// SAFETY:
2547
2586
// - Since `T` and `Wrapping<T>` have the same layout and bit validity
@@ -2565,6 +2604,8 @@ safety_comment! {
2565
2604
// since it may contain uninitialized bytes.
2566
2605
//
2567
2606
/// SAFETY:
2607
+ /// - `NoCell`: `MaybeUninit<T>` has `UnsafeCell`s exactly when `T` does, so
2608
+ /// `T: NoCell` guarantees that `MaybeUninit<T>` has no `UnsafeCell`s.
2568
2609
/// - `TryFromBytes` (with no validator), `FromZeroes`, `FromBytes`:
2569
2610
/// `MaybeUninit<T>` has no restrictions on its contents. Unfortunately,
2570
2611
/// in addition to bit validity, `TryFromBytes`, `FromZeroes` and
@@ -2581,6 +2622,7 @@ safety_comment! {
2581
2622
/// `FromBytes` and `RefFromBytes`, or if we introduce a separate
2582
2623
/// `NoCell`/`Freeze` trait, we can relax the trait bounds for `FromZeroes`
2583
2624
/// and `FromBytes`.
2625
+ unsafe_impl!( T : NoCell => NoCell for MaybeUninit <T >) ;
2584
2626
unsafe_impl!( T : TryFromBytes => TryFromBytes for MaybeUninit <T >) ;
2585
2627
unsafe_impl!( T : FromZeroes => FromZeroes for MaybeUninit <T >) ;
2586
2628
unsafe_impl!( T : FromBytes => FromBytes for MaybeUninit <T >) ;
@@ -2593,6 +2635,8 @@ safety_comment! {
2593
2635
/// accessing the inner value is safe (meaning that it's unsound to leave
2594
2636
/// the inner value uninitialized while exposing the `ManuallyDrop` to safe
2595
2637
/// code).
2638
+ /// - `NoCell`: `ManuallyDrop<T>` has `UnsafeCell`s exactly when `T` does,
2639
+ /// so `T: NoCell` guarantees that `ManuallyDrop<T>` has no `UnsafeCell`s.
2596
2640
/// - `FromZeroes`, `FromBytes`: Since it has the same layout as `T`, any
2597
2641
/// valid `T` is a valid `ManuallyDrop<T>`. If `T: FromZeroes`, a sequence
2598
2642
/// of zero bytes is a valid `T`, and thus a valid `ManuallyDrop<T>`. If
@@ -2616,6 +2660,7 @@ safety_comment! {
2616
2660
/// - Once [1] (added in
2617
2661
/// https://github.com/rust-lang/rust/pull/115522) is available on stable,
2618
2662
/// quote the stable docs instead of the nightly docs.
2663
+ unsafe_impl!( T : ?Sized + NoCell => NoCell for ManuallyDrop <T >) ;
2619
2664
unsafe_impl!( T : ?Sized + FromZeroes => FromZeroes for ManuallyDrop <T >) ;
2620
2665
unsafe_impl!( T : ?Sized + FromBytes => FromBytes for ManuallyDrop <T >) ;
2621
2666
unsafe_impl!( T : ?Sized + AsBytes => AsBytes for ManuallyDrop <T >) ;
@@ -2635,28 +2680,32 @@ safety_comment! {
2635
2680
///
2636
2681
/// Slices have the same layout as the section of the array they slice.
2637
2682
///
2638
- /// In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s
2639
- /// laid out back-to-back with no bytes in between. Therefore, `[T]` or `[T;
2640
- /// N]` are `FromZeroes`, `FromBytes`, and `AsBytes` if `T` is
2641
- /// (respectively). Furthermore, since an array/slice has "the same
2642
- /// alignment of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is.
2683
+ /// In other words, the layout and bit validity of a `[T]` or `[T; N]` is
2684
+ /// that of a sequence of `T`s laid out back-to-back with no bytes in
2685
+ /// between. Therefore, `[T]` or `[T; N]` are `NoCell`, `FromZeroes`,
2686
+ /// `FromBytes`, and `AsBytes` if `T` is (respectively). Furthermore, since
2687
+ /// an array/slice has "the same alignment of `T`", `[T]` and `[T; N]` are
2688
+ /// `Unaligned` if `T` is.
2643
2689
///
2644
2690
/// Note that we don't `assert_unaligned!` for slice types because
2645
2691
/// `assert_unaligned!` uses `align_of`, which only works for `Sized` types.
2646
2692
///
2647
2693
/// [1] https://doc.rust-lang.org/reference/type-layout.html#array-layout
2694
+ unsafe_impl!( const N : usize , T : NoCell => NoCell for [ T ; N ] ) ;
2648
2695
unsafe_impl!( const N : usize , T : FromZeroes => FromZeroes for [ T ; N ] ) ;
2649
2696
unsafe_impl!( const N : usize , T : FromBytes => FromBytes for [ T ; N ] ) ;
2650
2697
unsafe_impl!( const N : usize , T : AsBytes => AsBytes for [ T ; N ] ) ;
2651
2698
unsafe_impl!( const N : usize , T : Unaligned => Unaligned for [ T ; N ] ) ;
2652
2699
assert_unaligned!( [ ( ) ; 0 ] , [ ( ) ; 1 ] , [ u8 ; 0 ] , [ u8 ; 1 ] ) ;
2700
+ unsafe_impl!( T : NoCell => NoCell for [ T ] ) ;
2653
2701
unsafe_impl!( T : FromZeroes => FromZeroes for [ T ] ) ;
2654
2702
unsafe_impl!( T : FromBytes => FromBytes for [ T ] ) ;
2655
2703
unsafe_impl!( T : AsBytes => AsBytes for [ T ] ) ;
2656
2704
unsafe_impl!( T : Unaligned => Unaligned for [ T ] ) ;
2657
2705
}
2658
2706
safety_comment ! {
2659
2707
/// SAFETY:
2708
+ /// - `NoCell`: Raw pointers do not contain any `UnsafeCell`s.
2660
2709
/// - `FromZeroes`: For thin pointers (note that `T: Sized`), the zero
2661
2710
/// pointer is considered "null". [1] No operations which require
2662
2711
/// provenance are legal on null pointers, so this is not a footgun.
@@ -2668,9 +2717,17 @@ safety_comment! {
2668
2717
///
2669
2718
/// [1] TODO(https://github.com/rust-lang/rust/pull/116988): Cite the
2670
2719
/// documentation once this PR lands.
2720
+ unsafe_impl!( T => NoCell for * const T ) ;
2721
+ unsafe_impl!( T => NoCell for * mut T ) ;
2671
2722
unsafe_impl!( T => FromZeroes for * const T ) ;
2672
2723
unsafe_impl!( T => FromZeroes for * mut T ) ;
2673
2724
}
2725
+ safety_comment ! {
2726
+ /// SAFETY:
2727
+ /// Reference types do not contain any `UnsafeCell`s.
2728
+ unsafe_impl!( T : ?Sized => NoCell for & ' _ T ) ;
2729
+ unsafe_impl!( T : ?Sized => NoCell for & ' _ mut T ) ;
2730
+ }
2674
2731
2675
2732
// SIMD support
2676
2733
//
@@ -2721,6 +2778,7 @@ safety_comment! {
2721
2778
// also `TryFromBytes`, `FromZeroes`, `FromBytes`, or `AsBytes` respectively.
2722
2779
// - Since no upper bound is placed on the alignment, no SIMD type can be
2723
2780
// guaranteed to be `Unaligned`.
2781
+ // - `NoCell`: TODO
2724
2782
//
2725
2783
// Also per [1]:
2726
2784
//
@@ -2761,7 +2819,7 @@ mod simd {
2761
2819
safety_comment! {
2762
2820
/// SAFETY:
2763
2821
/// See comment on module definition for justification.
2764
- $( unsafe_impl!( $typ: TryFromBytes , FromZeroes , FromBytes , AsBytes ) ; ) *
2822
+ $( unsafe_impl!( $typ: NoCell , TryFromBytes , FromZeroes , FromBytes , AsBytes ) ; ) *
2765
2823
}
2766
2824
}
2767
2825
} ;
@@ -5344,6 +5402,7 @@ mod tests {
5344
5402
5345
5403
#[ test]
5346
5404
fn test_object_safety ( ) {
5405
+ fn _takes_no_cell ( _: & dyn NoCell ) { }
5347
5406
fn _takes_from_zeroes ( _: & dyn FromZeroes ) { }
5348
5407
fn _takes_from_bytes ( _: & dyn FromBytes ) { }
5349
5408
fn _takes_unaligned ( _: & dyn Unaligned ) { }
0 commit comments