Coverage Report

Created: 2026-06-18 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.52/src/pointer/invariant.rs
Line
Count
Source
1
// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0 OR MIT
2
//
3
// Copyright 2024 The Fuchsia Authors
4
//
5
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
6
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
7
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
8
// This file may not be copied, modified, or distributed except according to
9
// those terms.
10
11
#![allow(missing_copy_implementations, missing_debug_implementations, missing_docs)]
12
13
//! The parameterized invariants of a [`Ptr`][super::Ptr].
14
//!
15
//! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`])
16
//! triples implementing the [`Invariants`] trait.
17
18
/// The invariants of a [`Ptr`][super::Ptr].
19
pub trait Invariants: Sealed {
20
    type Aliasing: Aliasing;
21
    type Alignment: Alignment;
22
    type Validity: Validity;
23
}
24
25
impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) {
26
    type Aliasing = A;
27
    type Alignment = AA;
28
    type Validity = V;
29
}
30
31
/// The aliasing invariant of a [`Ptr`][super::Ptr].
32
///
33
/// All aliasing invariants must permit reading from the bytes of a pointer's
34
/// referent which are not covered by [`UnsafeCell`]s.
35
///
36
/// [`UnsafeCell`]: core::cell::UnsafeCell
37
pub trait Aliasing: Sealed {
38
    /// Is `Self` [`Exclusive`]?
39
    #[doc(hidden)]
40
    const IS_EXCLUSIVE: bool;
41
}
42
43
/// The alignment invariant of a [`Ptr`][super::Ptr].
44
pub trait Alignment: Sealed {
45
    #[doc(hidden)]
46
    #[must_use]
47
    fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
48
    where
49
        T: Copy + Read<I::Aliasing, R>,
50
        I: Invariants<Alignment = Self, Validity = Valid>,
51
        I::Aliasing: Reference;
52
}
53
54
/// The validity invariant of a [`Ptr`][super::Ptr].
55
///
56
/// # Safety
57
///
58
/// In this section, we will use `Ptr<T, V>` as a shorthand for `Ptr<T, I:
59
/// Invariants<Validity = V>>` for brevity.
60
///
61
/// Each `V: Validity` defines a set of bit values which may appear in the
62
/// referent of a `Ptr<T, V>`, denoted `S(T, V)`. Each `V: Validity`, in its
63
/// documentation, provides a definition of `S(T, V)` which must be valid for
64
/// all `T: ?Sized`. Any `V: Validity` must guarantee that this set is only a
65
/// function of the *bit validity* of the referent type, `T`, and not of any
66
/// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U`
67
/// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`.
68
///
69
/// It is guaranteed that the referent of any `ptr: Ptr<T, V>` is a member of
70
/// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for
71
/// any existing `Ptr`s or any `Ptr`s that that code creates.
72
///
73
/// An important implication of this guarantee is that it restricts what
74
/// transmutes are sound, where "transmute" is used in this context to refer to
75
/// changing the referent type or validity invariant of a `Ptr`, as either
76
/// change may change the set of bit values permitted to appear in the referent.
77
/// In particular, the following are necessary (but not sufficient) conditions
78
/// in order for a transmute from `src: Ptr<T, V>` to `dst: Ptr<U, W>` to be
79
/// sound:
80
/// - If `S(T, V) = S(U, W)`, then no restrictions apply; otherwise,
81
/// - If `dst` permits mutation of its referent (e.g. via `Exclusive` aliasing
82
///   or interior mutation under `Shared` aliasing), then it must hold that
83
///   `S(T, V) ⊇ S(U, W)` - in other words, the transmute must not expand the
84
///   set of allowed referent bit patterns. A violation of this requirement
85
///   would permit using `dst` to write `x` where `x ∈ S(U, W)` but `x ∉ S(T,
86
///   V)`, which would violate the guarantee that `src`'s referent may only
87
///   contain values in `S(T, V)`.
88
/// - If the referent may be mutated without going through `dst` while `dst` is
89
///   live (e.g. via interior mutation on a `Shared`-aliased `Ptr` or `&`
90
///   reference), then it must hold that `S(T, V) ⊆ S(U, W)` - in other words,
91
///   the transmute must not shrink the set of allowed referent bit patterns. A
92
///   violation of this requirement would permit using `src` or another
93
///   mechanism (e.g. a `&` reference used to derive `src`) to write `x` where
94
///   `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that
95
///   `dst`'s referent may only contain values in `S(U, W)`.
96
pub unsafe trait Validity: Sealed {
97
    const KIND: ValidityKind;
98
}
99
100
pub enum ValidityKind {
101
    Uninit,
102
    AsInitialized,
103
    Initialized,
104
    Valid,
105
}
106
107
/// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`].
108
///
109
/// # Safety
110
///
111
/// Given `A: Reference`, callers may assume that either `A = Shared` or `A =
112
/// Exclusive`.
113
pub trait Reference: Aliasing + Sealed {}
114
115
/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`.
116
///
117
/// The referent of a shared-aliased `Ptr` may be concurrently referenced by any
118
/// number of shared-aliased `Ptr` or `&T` references, or by any number of
119
/// `Ptr<U>` or `&U` references as permitted by `T`'s library safety invariants,
120
/// and may not be concurrently referenced by any exclusively-aliased `Ptr`s or
121
/// `&mut` references. The referent must not be mutated, except via
122
/// [`UnsafeCell`]s, and only when permitted by `T`'s library safety invariants.
123
///
124
/// [`UnsafeCell`]: core::cell::UnsafeCell
125
pub enum Shared {}
126
impl Aliasing for Shared {
127
    const IS_EXCLUSIVE: bool = false;
128
}
129
impl Reference for Shared {}
130
131
/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`.
132
///
133
/// The referent of an exclusively-aliased `Ptr` may not be concurrently
134
/// referenced by any other `Ptr`s or references, and may not be accessed (read
135
/// or written) other than via this `Ptr`.
136
pub enum Exclusive {}
137
impl Aliasing for Exclusive {
138
    const IS_EXCLUSIVE: bool = true;
139
}
140
impl Reference for Exclusive {}
141
142
/// It is unknown whether the pointer is aligned.
143
pub enum Unaligned {}
144
145
impl Alignment for Unaligned {
146
    #[inline(always)]
147
0
    fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
148
0
    where
149
0
        T: Copy + Read<I::Aliasing, R>,
150
0
        I: Invariants<Alignment = Self, Validity = Valid>,
151
0
        I::Aliasing: Reference,
152
    {
153
0
        (*ptr.into_unalign().as_ref()).into_inner()
154
0
    }
155
}
156
157
/// The referent is aligned: for `Ptr<T>`, the referent's address is a multiple
158
/// of the `T`'s alignment.
159
pub enum Aligned {}
160
impl Alignment for Aligned {
161
    #[inline(always)]
162
0
    fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T
163
0
    where
164
0
        T: Copy + Read<I::Aliasing, R>,
165
0
        I: Invariants<Alignment = Self, Validity = Valid>,
166
0
        I::Aliasing: Reference,
167
    {
168
0
        *ptr.as_ref()
169
0
    }
170
}
171
172
/// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized
173
/// bytes.
174
pub enum Uninit {}
175
// SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a
176
// function of any property of `T` other than its bit validity (in fact, it's
177
// not even a property of `T`'s bit validity, but this is more than we are
178
// required to uphold).
179
unsafe impl Validity for Uninit {
180
    const KIND: ValidityKind = ValidityKind::Uninit;
181
}
182
183
/// The byte ranges initialized in `T` are also initialized in the referent of a
184
/// `Ptr<T>`.
185
///
186
/// Formally: uninitialized bytes may only be present in `Ptr<T>`'s referent
187
/// where they are guaranteed to be present in `T`. This is a dynamic property:
188
/// if, at a particular byte offset, a valid enum discriminant is set, the
189
/// subsequent bytes may only have uninitialized bytes as specified by the
190
/// corresponding enum.
191
///
192
/// Formally, given `len = size_of_val_raw(ptr)`, at every byte offset, `b`, in
193
/// the range `[0, len)`:
194
/// - If, in any instance `t: T` of length `len`, the byte at offset `b` in `t`
195
///   is initialized, then the byte at offset `b` within `*ptr` must be
196
///   initialized.
197
/// - Let `c` be the contents of the byte range `[0, b)` in `*ptr`. Let `S` be
198
///   the subset of valid instances of `T` of length `len` which contain `c` in
199
///   the offset range `[0, b)`. If, in any instance of `t: T` in `S`, the byte
200
///   at offset `b` in `t` is initialized, then the byte at offset `b` in `*ptr`
201
///   must be initialized.
202
///
203
///   Pragmatically, this means that if `*ptr` is guaranteed to contain an enum
204
///   type at a particular offset, and the enum discriminant stored in `*ptr`
205
///   corresponds to a valid variant of that enum type, then it is guaranteed
206
///   that the appropriate bytes of `*ptr` are initialized as defined by that
207
///   variant's bit validity (although note that the variant may contain another
208
///   enum type, in which case the same rules apply depending on the state of
209
///   its discriminant, and so on recursively).
210
pub enum AsInitialized {}
211
// SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and
212
// is not a function of any property of `T` other than its bit validity.
213
unsafe impl Validity for AsInitialized {
214
    const KIND: ValidityKind = ValidityKind::AsInitialized;
215
}
216
217
/// The byte ranges in the referent are fully initialized. In other words, if
218
/// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`.
219
pub enum Initialized {}
220
// SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is
221
// not a function of any property of `T` other than its bit validity (in fact,
222
// it's not even a property of `T`'s bit validity, but this is more than we are
223
// required to uphold).
224
unsafe impl Validity for Initialized {
225
    const KIND: ValidityKind = ValidityKind::Initialized;
226
}
227
228
/// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any
229
/// library safety invariants.
230
pub enum Valid {}
231
// SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
232
// function of any property of `T` other than its bit validity.
233
unsafe impl Validity for Valid {
234
    const KIND: ValidityKind = ValidityKind::Valid;
235
}
236
237
/// # Safety
238
///
239
/// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV =
240
/// Initialized`.
241
pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {}
242
243
// SAFETY: `SV = DV = Uninit`.
244
unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {}
245
// SAFETY: `SV = DV = Initialized`.
246
unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {}
247
248
/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
249
///
250
/// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits
251
/// unsynchronized read operations. This can be because `A` is [`Exclusive`] or
252
/// because `T` does not permit interior mutation.
253
///
254
/// # Safety
255
///
256
/// `T: Read<A, R>` if either of the following conditions holds:
257
/// - `A` is [`Exclusive`]
258
/// - `T` implements [`Immutable`](crate::Immutable)
259
///
260
/// As a consequence, if `T: Read<A, R>`, then any `Ptr<T, (A, ...)>` is
261
/// permitted to perform unsynchronized reads from its referent.
262
pub trait Read<A: Aliasing, R> {}
263
264
impl<A: Aliasing, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
265
impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {}
266
267
/// Unsynchronized reads are permitted because only one live [`Ptr`](crate::Ptr)
268
/// or reference may exist to the referent bytes at a time.
269
#[derive(Copy, Clone, Debug)]
270
pub enum BecauseExclusive {}
271
272
/// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s or
273
/// references permit interior mutation.
274
#[derive(Copy, Clone, Debug)]
275
pub enum BecauseImmutable {}
276
277
use sealed::Sealed;
278
mod sealed {
279
    use super::*;
280
281
    pub trait Sealed {}
282
283
    impl Sealed for Shared {}
284
    impl Sealed for Exclusive {}
285
286
    impl Sealed for Unaligned {}
287
    impl Sealed for Aligned {}
288
289
    impl Sealed for Uninit {}
290
    impl Sealed for AsInitialized {}
291
    impl Sealed for Initialized {}
292
    impl Sealed for Valid {}
293
294
    impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}
295
296
    impl Sealed for BecauseImmutable {}
297
    impl Sealed for BecauseExclusive {}
298
}