zerocopy/pointer/aliasing_safety.rs
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
11use 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)]
27pub unsafe trait AliasingSafe<T: ?Sized, A: invariant::Aliasing, R: AliasingSafeReason> {}
28
29/// Used to prevent user implementations of `AliasingSafeReason`.
30mod 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)]
39pub trait AliasingSafeReason: sealed::Sealed {}
40impl<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)]
46pub enum BecauseExclusive {}
47impl 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)]
52pub enum BecauseImmutable {}
53impl 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`.
58unsafe 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.
65unsafe impl<A, T: ?Sized, U: ?Sized> AliasingSafe<T, A, BecauseImmutable> for U
66where
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.
83unsafe impl<A, T: ?Sized, U: ?Sized, R> AliasingSafe<U, A, (R,)> for T
84where
85 A: invariant::Aliasing,
86 R: AliasingSafeReason,
87 U: AliasingSafe<T, A, R>,
88{
89}