@@ -1832,26 +1832,28 @@ safety_comment! {
1832
1832
// `NonZeroXxx` is `AsBytes`, but not `FromZeroes` or `FromBytes`.
1833
1833
//
1834
1834
/// SAFETY:
1835
- /// - `AsBytes`: `NonZeroXxx` has the same layout as its associated
1836
- /// primitive. Since it is the same size, this guarantees it has no
1837
- /// padding - integers have no padding, and there's no room for padding
1838
- /// if it can represent all of the same values except 0.
1839
- /// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that
1840
- /// `Option<NonZeroU8>` and `Option<NonZeroI8>` both have size 1. [1] [2]
1841
- /// This is worded in a way that makes it unclear whether it's meant as a
1842
- /// guarantee, but given the purpose of those types, it's virtually
1843
- /// unthinkable that that would ever change. `Option` cannot be smaller
1844
- /// than its contained type, which implies that, and `NonZeroX8` are of
1845
- /// size 1 or 0. `NonZeroX8` can represent multiple states, so they cannot
1846
- /// be 0 bytes, which means that they must be 1 byte. The only valid
1847
- /// alignment for a 1-byte type is 1.
1835
+ /// `NonZeroXxx` has the same layout and bit validity as its associated
1836
+ /// primitive with the exception that 0 is not a valid instance. [1]
1837
+ /// - `AsBytes`: Since none of the associated primitives allow uninitialized
1838
+ /// bytes, neither do `NonZeroXxx`.
1839
+ /// - `Unaligned`: For `NonZeroU8` and `NonZeroI8`, we know that the `u8`
1840
+ /// and `i8` types have alignment 1 (this is true because they have size 1
1841
+ /// [2] and a type's alignment cannot be greater than its size [3]).
1848
1842
///
1849
- /// TODO(#429): Add quotes from documentation.
1843
+ /// [1] Per https://doc.rust-lang.org/beta/core/num/struct.NonZeroU16.html#layout-1:
1844
+ ///
1845
+ /// `NonZeroU16` is guaranteed to have the same layout and bit validity as
1846
+ /// `u16` with the exception that `0` is not a valid instance.
1847
+ ///
1848
+ /// TODO(https://github.com/rust-lang/rust/pull/94786): Once the Stable docs
1849
+ /// include this text, cite those docs instead of the Beta docs.
1850
+ ///
1851
+ /// [2] Per https://doc.rust-lang.org/reference/type-layout.html#primitive-data-layout,
1852
+ /// `size_of::<Type>()` for `u8` and `i8` is 1.
1853
+ ///
1854
+ /// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
1850
1855
///
1851
- /// [1] https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html
1852
- /// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html
1853
- /// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
1854
- /// that layout is the same as primitive layout.
1856
+ /// The size of a value is always a multiple of its alignment.
1855
1857
unsafe_impl!( NonZeroU8 : AsBytes , Unaligned ) ;
1856
1858
unsafe_impl!( NonZeroI8 : AsBytes , Unaligned ) ;
1857
1859
assert_unaligned!( NonZeroU8 , NonZeroI8 ) ;
@@ -1868,23 +1870,43 @@ safety_comment! {
1868
1870
}
1869
1871
safety_comment ! {
1870
1872
/// SAFETY:
1871
- /// - `FromZeroes`, `FromBytes`, `AsBytes`: The Rust compiler reuses `0`
1872
- /// value to represent `None`, so `size_of::<Option<NonZeroXxx>>() ==
1873
- /// size_of::<xxx>()`; see `NonZeroXxx` documentation.
1874
- /// - `Unaligned`: `NonZeroU8` and `NonZeroI8` document that
1875
- /// `Option<NonZeroU8>` and `Option<NonZeroI8>` both have size 1. [1] [2]
1876
- /// This is worded in a way that makes it unclear whether it's meant as a
1877
- /// guarantee, but given the purpose of those types, it's virtually
1878
- /// unthinkable that that would ever change. The only valid alignment for
1879
- /// a 1-byte type is 1.
1880
- ///
1881
- /// TODO(#429): Add quotes from documentation.
1882
- ///
1883
- /// [1] https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html
1884
- /// [2] https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html
1885
- ///
1886
- /// TODO(https://github.com/rust-lang/rust/pull/104082): Cite documentation
1887
- /// for layout guarantees.
1873
+ /// - `FromZeroes`: For all of these types, `T`, `transmute::<_,
1874
+ /// Option<T>>([0u8; size_of::<T>()])` is guaranteed to be sound. [1]
1875
+ /// - `FromBytes`, `AsBytes`: We know that transmuting from 0 produces
1876
+ /// `None`. [1] We further know that `NonZeroXxx` has the same size and
1877
+ /// alignment as `Option<NonZeroXxx>`. [2] Finally, we know that
1878
+ /// `NonZeroXxx` has the same bit validity as `Xxx` with the exception of
1879
+ /// 0. [2] Since `Xxx: FromBytes`, in order for `Option<NonZeroXxx>:
1880
+ /// FromBytes`, it only needs to be the case that 0 is a valid instance of
1881
+ /// `Option<NonZeroXxx>`, which is guaranteed. Since `Xxx: AsBytes`, it
1882
+ /// only needs to be the case that `Option::<NonZeroXxx>::None` has all of
1883
+ /// its bytes initialized. [3]
1884
+ /// - `Unaligned`: `NonZeroU8` and `NonZeroI8` both implement `Unaligned`,
1885
+ /// and so have alignment 1. Per [2], `Option<NonZeroU8>` and
1886
+ /// `Option<NonZeroI8>` have the same alignment.
1887
+ ///
1888
+ /// [1] Per https://doc.rust-lang.org/nightly/core/option/#representation,
1889
+ /// it is always true that, for `T` = `num::NonZero*`, `transmute::<_,
1890
+ /// Option<T>>([0u8; size_of::<T>()])` and produces `Option::<T>::None`.
1891
+ ///
1892
+ /// TODO(https://github.com/rust-lang/rust/pull/115333): Once the Stable
1893
+ /// docs include this text, cite those docs instead of the Nightly docs.
1894
+ ///
1895
+ /// [2] Per https://doc.rust-lang.org/beta/core/num/struct.NonZeroU16.html#layout-1:
1896
+ ///
1897
+ /// `NonZeroU16` is guaranteed to have the same layout and bit validity as
1898
+ /// `u16` with the exception that `0` is not a valid instance. ...
1899
+ ///
1900
+ /// Thanks to the null pointer optimization, `NonZeroU16` and
1901
+ /// `Option<NonZeroU16>` are guaranteed to have the same size and
1902
+ /// alignment.
1903
+ ///
1904
+ /// TODO(https://github.com/rust-lang/rust/pull/94786): Once the Stable docs
1905
+ /// include this text, cite those docs instead of the Beta docs.
1906
+ ///
1907
+ /// [3] TODO(#429): Cite documentation that guarantees that
1908
+ /// `Option::<T>::None` has all of its bytes initialized where `T` is a
1909
+ /// type subject to the null-pointer optimization (NPO).
1888
1910
unsafe_impl!( Option <NonZeroU8 >: FromZeroes , FromBytes , AsBytes , Unaligned ) ;
1889
1911
unsafe_impl!( Option <NonZeroI8 >: FromZeroes , FromBytes , AsBytes , Unaligned ) ;
1890
1912
assert_unaligned!( Option <NonZeroU8 >, Option <NonZeroI8 >) ;
0 commit comments