rust_spec/core_impls/
wrappers.rs1#[cfg(feature = "alloc")]
2use alloc::{string::String, vec::Vec};
3use core::{
4 cmp::Reverse,
5 convert::Infallible,
6 marker::{PhantomData, PhantomPinned},
7 mem::{ManuallyDrop, MaybeUninit},
8 num::{NonZero, Saturating, Wrapping},
9};
10
11#[cfg(feature = "alloc")]
12use crate::drop::{AutoDrop, CustomDrop};
13use crate::{
14 NonOpaque, RustSpec, Stable, Unstable,
15 drop::{NeedsDrop, NoDrop},
16 layout::{NonRobust, Robust},
17 mutability::{Exclusive, WithInterior, WithoutInterior},
18 niche::{WithNiche, WithoutNiche},
19 size,
20};
21
22macro_rules! non_zero_derive {
23 ($($primitive:ty),+ $(,)?) => {$(
24 unsafe impl RustSpec for NonZero<$primitive> {
25 type Layout = Stable;
26 type Size = size::Sized<crate::Gt<crate::Zero>>;
27 type __Alignment = <$primitive as RustSpec>::__Alignment;
28 type Trap = NonRobust;
29 type Niche = WithNiche<Stable>;
30 type Drop = NoDrop;
31 type Mutability = Exclusive<WithoutInterior>;
32 type Opacity = NonOpaque;
33 type __IndirectTrap = Robust;
34 }
35 )+};
36}
37
38macro_rules! stable_robust_zst {
39 (($($generics:tt)*) => $ty:ty) => {
40 unsafe impl<$($generics)*> RustSpec for $ty {
41 type Layout = Stable;
42 type Size = size::Sized<size::Zero>;
43 type __Alignment = crate::One;
44 type Trap = Robust;
45 type Niche = WithoutNiche;
46 type Drop = NoDrop;
47 type Mutability = Exclusive<WithoutInterior>;
48 type Opacity = NonOpaque;
49 type __IndirectTrap = Robust;
50 }
51 };
52}
53
54macro_rules! transparent_wrapper {
55 (($($generics:tt)*) => $ty:ty) => {
56 unsafe impl<$($generics)*> RustSpec for $ty
57 where
58 T::Drop: crate::drop::DropKind,
59 {
60 type Layout = T::Layout;
61 type Size = T::Size;
62 type __Alignment = T::__Alignment;
63 type Trap = T::Trap;
64 type Niche = T::Niche;
65 type Drop = NeedsDrop<T::Drop>;
66 type Mutability = T::Mutability;
67 type Opacity = NonOpaque;
68 type __IndirectTrap = T::__IndirectTrap;
69 }
70 };
71}
72
73non_zero_derive!(
74 u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize
75);
76
77stable_robust_zst!(() => ());
78stable_robust_zst!(() => Infallible);
79stable_robust_zst!(() => PhantomPinned);
80stable_robust_zst!((T: ?Sized) => PhantomData<T>);
81
82transparent_wrapper!((T: RustSpec) => Reverse<T>);
83transparent_wrapper!((T: RustSpec) => Wrapping<T>);
84transparent_wrapper!((T: RustSpec) => Saturating<T>);
85
86unsafe impl<T: RustSpec + ?Sized> RustSpec for ManuallyDrop<T> {
87 type Layout = T::Layout;
88 type Size = T::Size;
89 type __Alignment = T::__Alignment;
90 type Trap = T::Trap;
91 type Niche = T::Niche;
92 type Drop = NoDrop;
93 type Mutability = T::Mutability;
94 type Opacity = NonOpaque;
95 type __IndirectTrap = T::__IndirectTrap;
96}
97
98const _: () = {
100 pub trait UninitMutability {
101 type Output;
102 }
103
104 impl UninitMutability for Exclusive<WithoutInterior> {
105 type Output = Self;
106 }
107 impl<R> UninitMutability for WithInterior<R> {
108 type Output = WithInterior<Robust>;
109 }
110 impl<R> UninitMutability for Exclusive<WithInterior<R>> {
111 type Output = Exclusive<WithInterior<Robust>>;
112 }
113
114 unsafe impl<T: RustSpec<Mutability: UninitMutability>> RustSpec for MaybeUninit<T> {
115 type Layout = T::Layout;
116 type Size = T::Size;
117 type __Alignment = T::__Alignment;
118 type Trap = Robust;
119 type Niche = WithoutNiche;
120 type Drop = NoDrop;
121 type Mutability = <T::Mutability as UninitMutability>::Output;
124 type Opacity = NonOpaque;
125 type __IndirectTrap = Robust;
126 }
127};
128
129unsafe impl RustSpec for str {
130 type Layout = Stable;
131 type Size = size::MetaSized<size::SliceLike>;
132 type __Alignment = crate::One;
133 type Trap = NonRobust;
134 type Niche = WithNiche<Unstable>;
136 type Drop = NoDrop;
137 type Mutability = Exclusive<WithoutInterior>;
138 type Opacity = NonOpaque;
139 type __IndirectTrap = Robust;
140}
141#[cfg(feature = "alloc")]
142unsafe impl RustSpec for String {
143 type Layout = Unstable;
144 type Size = size::Sized<crate::Gt<crate::Zero>>;
145 type __Alignment = <usize as RustSpec>::__Alignment;
146 type Trap = NonRobust;
147 type Niche = WithNiche<Unstable>;
148 type Drop = AutoDrop;
149 type Mutability = Exclusive<WithoutInterior>;
150 type Opacity = NonOpaque;
151 type __IndirectTrap = NonRobust;
152}
153
154#[cfg(feature = "alloc")]
155unsafe impl<T: RustSpec<Mutability: crate::mutability::PointerMutability>> RustSpec for Vec<T> {
156 type Layout = Unstable;
157 type Size = size::Sized<crate::Gt<crate::Zero>>;
158 type __Alignment = <usize as RustSpec>::__Alignment;
159 type Trap = NonRobust;
160 type Niche = WithNiche<Unstable>;
161 type Drop = CustomDrop<AutoDrop>;
162 type Mutability = <T::Mutability as crate::mutability::PointerMutability>::Output;
163 type Opacity = NonOpaque;
164 type __IndirectTrap = T::Trap;
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170 use core::cell::{Cell, UnsafeCell};
171 use static_assertions::assert_impl_all;
172
173 #[test]
174 fn maybe_uninit_preserves_mutability_without_inner_traps() {
175 assert_impl_all!(MaybeUninit<bool>:
176 RustSpec<Mutability = Exclusive<WithoutInterior>, Trap = Robust>);
177 assert_impl_all!(MaybeUninit<UnsafeCell<bool>>:
178 RustSpec<Mutability = WithInterior<Robust>, Trap = Robust>);
179 assert_impl_all!(MaybeUninit<Cell<bool>>:
180 RustSpec<Mutability = WithInterior<Robust>, Trap = Robust>);
181 assert_impl_all!(MaybeUninit<&'static UnsafeCell<bool>>:
182 RustSpec<Mutability = Exclusive<WithInterior<Robust>>, Trap = Robust>);
183 assert_impl_all!([MaybeUninit<UnsafeCell<bool>>; 2]:
184 RustSpec<Mutability = WithInterior<Robust>>);
185 assert_impl_all!(UnsafeCell<MaybeUninit<bool>>:
186 RustSpec<Mutability = WithInterior<Robust>>);
187 assert_impl_all!(MaybeUninit<MaybeUninit<UnsafeCell<bool>>>:
188 RustSpec<Mutability = WithInterior<Robust>>);
189 assert_impl_all!(ManuallyDrop<UnsafeCell<bool>>:
190 RustSpec<Mutability = WithInterior<NonRobust>, Trap = NonRobust>);
191
192 #[cfg(feature = "alloc")]
193 {
194 use alloc::boxed::Box;
195 assert_impl_all!(Box<MaybeUninit<UnsafeCell<bool>>>:
196 RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
197 assert_impl_all!(MaybeUninit<Box<UnsafeCell<bool>>>:
198 RustSpec<Mutability = Exclusive<WithInterior<Robust>>, Trap = Robust>);
199 }
200 }
201}