-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds the `pointer::aliasing_safety::AliasingSafe` trait, which is implemented for pointer conversions which do not violate aliasing. This can happen either because the aliasing is exclusive or because neither type contains `UnsafeCell`s. This paves the way for us to remove `Immutable` bounds from some of our API, including from some derives. Makes progress on #251 Co-authored-by: Jack Wrenn <jswrenn@amazon.com>
- Loading branch information
Showing
5 changed files
with
162 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright 2024 The Fuchsia Authors | ||
// | ||
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 | ||
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT | ||
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. | ||
// This file may not be copied, modified, or distributed except according to | ||
// those terms. | ||
|
||
//! Machinery for statically proving the "aliasing-safety" of a `Ptr`. | ||
use crate::{invariant, Immutable}; | ||
|
||
/// Pointer conversions which do not violate aliasing. | ||
/// | ||
/// `U: AliasingSafe<T, A, R>` implies that a pointer conversion from `T` to `U` | ||
/// does not violate the aliasing invariant, `A`. This can be because `A` is | ||
/// [`Exclusive`] or because neither `T` nor `U` permit interior mutability. | ||
/// | ||
/// # Safety | ||
/// | ||
/// `U: AliasingSafe<T, A, R>` if either of the following conditions holds: | ||
/// - `A` is [`Exclusive`] | ||
/// - `T` and `U` both implement [`Immutable`] | ||
/// | ||
/// [`Exclusive`]: crate::pointer::invariant::Exclusive | ||
#[doc(hidden)] | ||
pub unsafe trait AliasingSafe<T: ?Sized, A: invariant::Aliasing, R: AliasingSafeReason> {} | ||
|
||
/// Used to prevent user implementations of `AliasingSafeReason`. | ||
mod sealed { | ||
pub trait Sealed {} | ||
|
||
impl Sealed for super::BecauseExclusive {} | ||
impl Sealed for super::BecauseImmutable {} | ||
impl<S: Sealed> Sealed for (S,) {} | ||
} | ||
|
||
#[doc(hidden)] | ||
pub trait AliasingSafeReason: sealed::Sealed {} | ||
impl<R: AliasingSafeReason> AliasingSafeReason for (R,) {} | ||
|
||
/// The conversion is safe because only one live `Ptr` or reference may exist to | ||
/// the referent bytes at a time. | ||
#[derive(Copy, Clone, Debug)] | ||
#[doc(hidden)] | ||
pub enum BecauseExclusive {} | ||
impl AliasingSafeReason for BecauseExclusive {} | ||
|
||
/// The conversion is safe because no live `Ptr`s or references permit mutation. | ||
#[derive(Copy, Clone, Debug)] | ||
#[doc(hidden)] | ||
pub enum BecauseImmutable {} | ||
impl AliasingSafeReason for BecauseImmutable {} | ||
|
||
/// SAFETY: `T: AliasingSafe<Exclusive, BecauseExclusive>` because for all | ||
/// `Ptr<'a, T, I>` such that `I::Aliasing = Exclusive`, there cannot exist | ||
/// other live references to the memory referenced by `Ptr`. | ||
unsafe impl<T: ?Sized, U: ?Sized> AliasingSafe<T, invariant::Exclusive, BecauseExclusive> for U {} | ||
|
||
/// SAFETY: `U: AliasingSafe<T, A, BecauseNoCell>` because for all `Ptr<'a, T, | ||
/// I>` and `Ptr<'a, U, I>` such that `I::Aliasing = A`, all live references and | ||
/// live `Ptr`s agree, by invariant on `Immutable`, that the referenced bytes | ||
/// contain no `UnsafeCell`s, and thus do not permit mutation except via | ||
/// exclusive aliasing. | ||
unsafe impl<A, T: ?Sized, U: ?Sized> AliasingSafe<T, A, BecauseImmutable> for U | ||
where | ||
A: invariant::Aliasing, | ||
T: Immutable, | ||
U: Immutable, | ||
{ | ||
} | ||
|
||
/// This ensures that `U: AliasingSafe<T, A>` implies `T: AliasingSafe<U, A>` in | ||
/// a manner legible to rustc, which in turn means we can write simpler bounds in | ||
/// some places. | ||
/// | ||
/// SAFETY: Per `U: AliasingSafe<T, A, R>`, either: | ||
/// - `A` is `Exclusive` | ||
/// - `T` and `U` both implement `Immutable` | ||
/// | ||
/// Neither property depends on which of `T` and `U` are in the `Self` position | ||
/// vs the first type parameter position. | ||
unsafe impl<A, T: ?Sized, U: ?Sized, R> AliasingSafe<U, A, (R,)> for T | ||
where | ||
A: invariant::Aliasing, | ||
R: AliasingSafeReason, | ||
U: AliasingSafe<T, A, R>, | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.