1use core::{convert::Infallible, marker::PhantomData, ops::Add};
3
4use crate::Sum;
5
6pub enum WithoutInterior {}
8
9#[sealed::sealed]
11pub trait ExclusiveKind {}
12
13#[sealed::sealed]
14impl ExclusiveKind for WithoutInterior {}
15
16#[sealed::sealed]
17impl<R> ExclusiveKind for WithInterior<R> {}
18
19pub struct Exclusive<I: ExclusiveKind>(PhantomData<I>, Infallible);
22
23pub struct WithInterior<R>(PhantomData<R>, Infallible);
27
28#[sealed::sealed]
30pub trait PointerMutability {
31 type Output;
32}
33
34#[sealed::sealed]
35impl<I: ExclusiveKind> PointerMutability for Exclusive<I> {
36 type Output = Self;
37}
38#[sealed::sealed]
39impl<R> PointerMutability for WithInterior<R> {
40 type Output = Exclusive<Self>;
41}
42
43impl Add<Self> for WithoutInterior {
44 type Output = Self;
45
46 fn add(self, _: Self) -> Self::Output {
47 unreachable!()
48 }
49}
50impl<R> Add<WithInterior<R>> for WithoutInterior {
51 type Output = WithInterior<R>;
52
53 fn add(self, _: WithInterior<R>) -> Self::Output {
54 unreachable!()
55 }
56}
57impl<R> Add<WithoutInterior> for WithInterior<R> {
58 type Output = Self;
59
60 fn add(self, _: WithoutInterior) -> Self::Output {
61 unreachable!()
62 }
63}
64impl<L: Add<R>, R> Add<WithInterior<R>> for WithInterior<L> {
65 type Output = WithInterior<L::Output>;
66
67 fn add(self, _: WithInterior<R>) -> Self::Output {
68 unreachable!()
69 }
70}
71impl<L: ExclusiveKind + Add<R, Output: ExclusiveKind>, R: ExclusiveKind> Add<Exclusive<R>>
72 for Exclusive<L>
73{
74 type Output = Exclusive<L::Output>;
75
76 fn add(self, _: Exclusive<R>) -> Self::Output {
77 unreachable!()
78 }
79}
80impl<I: ExclusiveKind + Add<WithInterior<R>>, R> Add<WithInterior<R>> for Exclusive<I> {
81 type Output = Sum<I, WithInterior<R>>;
82
83 fn add(self, _: WithInterior<R>) -> Self::Output {
84 unreachable!()
85 }
86}
87impl<I: ExclusiveKind, R> Add<Exclusive<I>> for WithInterior<R>
88where
89 Self: Add<I>,
90{
91 type Output = Sum<Self, I>;
92
93 fn add(self, _: Exclusive<I>) -> Self::Output {
94 unreachable!()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 #[cfg(feature = "alloc")]
101 use alloc::{boxed::Box, vec::Vec};
102
103 use static_assertions::assert_impl_all;
104
105 use crate::{
106 RustSpec, Stable, Unstable,
107 layout::{NonRobust, Robust},
108 mutability::{Exclusive, WithInterior, WithoutInterior},
109 niche::{WithNiche, WithoutNiche},
110 size::Sized as RustSpecSized,
111 };
112
113 #[test]
114 fn exclusive_kind_accepts_only_reachability_markers() {
115 use super::{ExclusiveKind, WithoutInterior};
116 assert_impl_all!(WithoutInterior: ExclusiveKind);
117 assert_impl_all!(WithInterior<Robust>: ExclusiveKind);
118 assert_impl_all!(WithInterior<NonRobust>: ExclusiveKind);
119 static_assertions::assert_not_impl_any!(Exclusive<WithoutInterior>: ExclusiveKind);
120 static_assertions::assert_not_impl_any!(u8: ExclusiveKind);
121 }
122
123 #[test]
124 fn indirect_and_aggregate_mutability() {
125 use core::cell::UnsafeCell;
126 use core::ptr::NonNull;
127 assert_impl_all!(&&UnsafeCell<u8>: RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
128 assert_impl_all!(*const UnsafeCell<u8>: RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
129 assert_impl_all!(NonNull<UnsafeCell<u8>>: RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
130 assert_impl_all!((u8, &UnsafeCell<u8>): RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
131 assert_impl_all!((UnsafeCell<u8>, &UnsafeCell<u8>): RustSpec<Mutability = WithInterior<Robust>>);
132 #[cfg(feature = "alloc")]
133 assert_impl_all!(Box<Box<UnsafeCell<u8>>>: RustSpec<Mutability = Exclusive<WithInterior<Robust>>>);
134 }
135
136 #[test]
137 fn mixed_mutability_preserves_reachable_robustness() {
138 use core::cell::UnsafeCell;
139
140 type Mixed = (UnsafeCell<u8>, &'static UnsafeCell<bool>);
141 type Reversed = (&'static UnsafeCell<bool>, UnsafeCell<u8>);
142 assert_impl_all!(Mixed: RustSpec<Mutability = WithInterior<NonRobust>>);
143 assert_impl_all!(Reversed: RustSpec<Mutability = WithInterior<NonRobust>>);
144 assert_impl_all!(&&Mixed: RustSpec<Mutability = Exclusive<WithInterior<NonRobust>>>);
145 assert_impl_all!((u8, &Mixed): RustSpec<Mutability = Exclusive<WithInterior<NonRobust>>>);
146 assert_impl_all!((UnsafeCell<u8>, &Mixed): RustSpec<Mutability = WithInterior<NonRobust>>);
147 assert_impl_all!((&Mixed, UnsafeCell<u8>): RustSpec<Mutability = WithInterior<NonRobust>>);
148 assert_impl_all!((bool, UnsafeCell<u8>): RustSpec<Trap = NonRobust, Mutability = WithInterior<Robust>>);
149 }
150
151 #[test]
152 fn mutability_family_tracks_shared_mutability() {
153 use core::{
154 cell::{Cell, UnsafeCell},
155 ptr::NonNull,
156 };
157
158 assert_impl_all!(u8:
159 RustSpec<
160 Layout = Stable,
161 Size = RustSpecSized<crate::Gt<crate::Zero>>,
162 __Alignment = crate::One,
163 Trap = Robust,
164 Niche = WithoutNiche,
165 Mutability = Exclusive<WithoutInterior>,
166 __IndirectTrap = Robust,
167 >,
168 );
169 assert_impl_all!(UnsafeCell<u8>:
170 RustSpec<
171 Layout = Stable,
172 Size = RustSpecSized<crate::Gt<crate::Zero>>,
173 __Alignment = crate::One,
174 Trap = Robust,
175 Niche = WithoutNiche,
176 Mutability = WithInterior<Robust>,
177 __IndirectTrap = Robust,
178 >,
179 );
180 assert_impl_all!(Cell<u8>:
181 RustSpec<
182 Layout = Stable,
183 Size = RustSpecSized<crate::Gt<crate::Zero>>,
184 __Alignment = crate::One,
185 Trap = Robust,
186 Niche = WithoutNiche,
187 Mutability = WithInterior<Robust>,
188 __IndirectTrap = Robust,
189 >,
190 );
191 assert_impl_all!((UnsafeCell<u8>, UnsafeCell<u8>):
192 RustSpec<
193 Layout = Unstable,
194 Size = RustSpecSized<crate::Gt<crate::Zero>>,
195 __Alignment = crate::One,
196 Trap = Robust,
197 Niche = WithoutNiche,
198 Mutability = WithInterior<Robust>,
199 __IndirectTrap = Robust,
200 >,
201 );
202 assert_impl_all!((UnsafeCell<u8>, u8):
203 RustSpec<
204 Layout = Unstable,
205 Size = RustSpecSized<crate::Gt<crate::Zero>>,
206 __Alignment = crate::One,
207 Trap = Robust,
208 Niche = WithoutNiche,
209 Mutability = WithInterior<Robust>,
210 __IndirectTrap = Robust,
211 >,
212 );
213 assert_impl_all!([UnsafeCell<u8>; 2]:
214 RustSpec<
215 Layout = Stable,
216 Size = RustSpecSized<crate::Gt<crate::Zero>>,
217 __Alignment = crate::One,
218 Trap = Robust,
219 Niche = WithoutNiche,
220 Mutability = WithInterior<Robust>,
221 __IndirectTrap = Robust,
222 >,
223 );
224 assert_impl_all!([u8; 2]:
225 RustSpec<
226 Layout = Stable,
227 Size = RustSpecSized<crate::Gt<crate::Zero>>,
228 __Alignment = crate::One,
229 Trap = Robust,
230 Niche = WithoutNiche,
231 Mutability = Exclusive<WithoutInterior>,
232 __IndirectTrap = Robust,
233 >,
234 );
235 assert_impl_all!(&UnsafeCell<u8>:
236 RustSpec<
237 Layout = Stable,
238 Size = RustSpecSized<crate::Gt<crate::Zero>>,
239 __Alignment = <usize as RustSpec>::__Alignment,
240 Trap = NonRobust,
241 Niche = WithNiche<Stable>,
242 Mutability = Exclusive<WithInterior<Robust>>,
243 __IndirectTrap = Robust,
244 >,
245 );
246 assert_impl_all!(&mut UnsafeCell<u8>:
247 RustSpec<
248 Layout = Stable,
249 Size = RustSpecSized<crate::Gt<crate::Zero>>,
250 __Alignment = <usize as RustSpec>::__Alignment,
251 Trap = NonRobust,
252 Niche = WithNiche<Stable>,
253 Mutability = Exclusive<WithInterior<Robust>>,
254 __IndirectTrap = Robust,
255 >,
256 );
257 assert_impl_all!(*const UnsafeCell<u8>:
258 RustSpec<
259 Layout = Stable,
260 Size = RustSpecSized<crate::Gt<crate::Zero>>,
261 __Alignment = <usize as RustSpec>::__Alignment,
262 Trap = Robust,
263 Niche = WithoutNiche,
264 Mutability = Exclusive<WithInterior<Robust>>,
265 __IndirectTrap = Robust,
266 >,
267 );
268 assert_impl_all!(*mut UnsafeCell<u8>:
269 RustSpec<
270 Layout = Stable,
271 Size = RustSpecSized<crate::Gt<crate::Zero>>,
272 __Alignment = <usize as RustSpec>::__Alignment,
273 Trap = Robust,
274 Niche = WithoutNiche,
275 Mutability = Exclusive<WithInterior<Robust>>,
276 __IndirectTrap = Robust,
277 >,
278 );
279 assert_impl_all!(NonNull<UnsafeCell<u8>>:
280 RustSpec<
281 Layout = Stable,
282 Size = RustSpecSized<crate::Gt<crate::Zero>>,
283 __Alignment = <usize as RustSpec>::__Alignment,
284 Trap = NonRobust,
285 Niche = WithNiche<Stable>,
286 Mutability = Exclusive<WithInterior<Robust>>,
287 __IndirectTrap = Robust,
288 >,
289 );
290 assert_impl_all!(Option<UnsafeCell<u8>>:
291 RustSpec<
292 Layout = Unstable,
293 Size = RustSpecSized<crate::Gt<crate::Zero>>,
294 __Alignment = crate::One,
295 Trap = NonRobust,
296 Niche = WithNiche<Unstable>,
297 Mutability = WithInterior<Robust>,
298 __IndirectTrap = Robust,
299 >,
300 );
301
302 #[cfg(feature = "alloc")]
303 assert_impl_all!(Box<UnsafeCell<u8>>:
304 RustSpec<
305 Layout = Stable,
306 Size = RustSpecSized<crate::Gt<crate::Zero>>,
307 __Alignment = <usize as RustSpec>::__Alignment,
308 Trap = NonRobust,
309 Niche = WithNiche<Stable>,
310 Mutability = Exclusive<WithInterior<Robust>>,
311 __IndirectTrap = Robust,
312 >,
313 );
314 #[cfg(feature = "alloc")]
315 assert_impl_all!(Box<[UnsafeCell<u8>]>:
316 RustSpec<
317 Layout = Unstable,
318 Size = RustSpecSized<crate::Gt<crate::Zero>>,
319 __Alignment = <usize as RustSpec>::__Alignment,
320 Trap = NonRobust,
321 Niche = WithNiche<Unstable>,
322 Mutability = Exclusive<WithInterior<Robust>>,
323 __IndirectTrap = Robust,
324 >,
325 );
326 #[cfg(feature = "alloc")]
327 assert_impl_all!(Vec<UnsafeCell<u8>>:
328 RustSpec<
329 Layout = Unstable,
330 Size = RustSpecSized<crate::Gt<crate::Zero>>,
331 __Alignment = <usize as RustSpec>::__Alignment,
332 Trap = NonRobust,
333 Niche = WithNiche<Unstable>,
334 Mutability = Exclusive<WithInterior<Robust>>,
335 __IndirectTrap = Robust,
336 >,
337 );
338 }
339}