1 | // Copyright 2024 The Fuchsia Authors |
2 | // |
3 | // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 |
4 | // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT |
5 | // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. |
6 | // This file may not be copied, modified, or distributed except according to |
7 | // those terms. |
8 | |
9 | //! Machinery for statically proving the "aliasing-safety" of a `Ptr`. |
10 | |
11 | use crate::{invariant, Immutable}; |
12 | |
13 | /// Pointer conversions which do not violate aliasing. |
14 | /// |
15 | /// `U: AliasingSafe<T, A, R>` implies that a pointer conversion from `T` to `U` |
16 | /// does not violate the aliasing invariant, `A`. This can be because `A` is |
17 | /// [`Exclusive`] or because neither `T` nor `U` permit interior mutability. |
18 | /// |
19 | /// # Safety |
20 | /// |
21 | /// `U: AliasingSafe<T, A, R>` if either of the following conditions holds: |
22 | /// - `A` is [`Exclusive`] |
23 | /// - `T` and `U` both implement [`Immutable`] |
24 | /// |
25 | /// [`Exclusive`]: crate::pointer::invariant::Exclusive |
26 | #[doc (hidden)] |
27 | pub unsafe trait AliasingSafe<T: ?Sized, A: invariant::Aliasing, R: AliasingSafeReason> {} |
28 | |
29 | /// Used to prevent user implementations of `AliasingSafeReason`. |
30 | mod sealed { |
31 | pub trait Sealed {} |
32 | |
33 | impl Sealed for super::BecauseExclusive {} |
34 | impl Sealed for super::BecauseImmutable {} |
35 | impl<S: Sealed> Sealed for (S,) {} |
36 | } |
37 | |
38 | #[doc (hidden)] |
39 | pub trait AliasingSafeReason: sealed::Sealed {} |
40 | impl<R: AliasingSafeReason> AliasingSafeReason for (R,) {} |
41 | |
42 | /// The conversion is safe because only one live `Ptr` or reference may exist to |
43 | /// the referent bytes at a time. |
44 | #[derive(Copy, Clone, Debug)] |
45 | #[doc (hidden)] |
46 | pub enum BecauseExclusive {} |
47 | impl AliasingSafeReason for BecauseExclusive {} |
48 | |
49 | /// The conversion is safe because no live `Ptr`s or references permit mutation. |
50 | #[derive(Copy, Clone, Debug)] |
51 | #[doc (hidden)] |
52 | pub enum BecauseImmutable {} |
53 | impl AliasingSafeReason for BecauseImmutable {} |
54 | |
55 | /// SAFETY: `T: AliasingSafe<Exclusive, BecauseExclusive>` because for all |
56 | /// `Ptr<'a, T, I>` such that `I::Aliasing = Exclusive`, there cannot exist |
57 | /// other live references to the memory referenced by `Ptr`. |
58 | unsafe impl<T: ?Sized, U: ?Sized> AliasingSafe<T, invariant::Exclusive, BecauseExclusive> for U {} |
59 | |
60 | /// SAFETY: `U: AliasingSafe<T, A, BecauseNoCell>` because for all `Ptr<'a, T, |
61 | /// I>` and `Ptr<'a, U, I>` such that `I::Aliasing = A`, all live references and |
62 | /// live `Ptr`s agree, by invariant on `Immutable`, that the referenced bytes |
63 | /// contain no `UnsafeCell`s, and thus do not permit mutation except via |
64 | /// exclusive aliasing. |
65 | unsafe impl<A, T: ?Sized, U: ?Sized> AliasingSafe<T, A, BecauseImmutable> for U |
66 | where |
67 | A: invariant::Aliasing, |
68 | T: Immutable, |
69 | U: Immutable, |
70 | { |
71 | } |
72 | |
73 | /// This ensures that `U: AliasingSafe<T, A>` implies `T: AliasingSafe<U, A>` in |
74 | /// a manner legible to rustc, which in turn means we can write simpler bounds in |
75 | /// some places. |
76 | /// |
77 | /// SAFETY: Per `U: AliasingSafe<T, A, R>`, either: |
78 | /// - `A` is `Exclusive` |
79 | /// - `T` and `U` both implement `Immutable` |
80 | /// |
81 | /// Neither property depends on which of `T` and `U` are in the `Self` position |
82 | /// vs the first type parameter position. |
83 | unsafe impl<A, T: ?Sized, U: ?Sized, R> AliasingSafe<U, A, (R,)> for T |
84 | where |
85 | A: invariant::Aliasing, |
86 | R: AliasingSafeReason, |
87 | U: AliasingSafe<T, A, R>, |
88 | { |
89 | } |
90 | |