Skip to content

Commit

Permalink
[pointer] Fix Ptr[Inner] variance
Browse files Browse the repository at this point in the history
Previously, `Ptr<'a, T>` and `PtrInner<'a, T>` documented themselves to
be covariant in both `'a` and `T`. This was true for `PtrInner`, but not
for `Ptr`, which used GATs, which are invariant. This is also not the
desired variance: for `Exclusive` aliasing, the desired variance matches
that of `&mut` references - namely, covariant in `'a` but invariant in
`T`.

This commit fixes this by making `Ptr<'a, T>` and `PtrInner<'a, T>`
unconditionally covariant in `'a` and invariant in `T`.

gherrit-pr-id: I29f8429d9d7b14026313f030f8dc1e895a98ad56
  • Loading branch information
joshlf committed Feb 18, 2025
1 parent 9322a2c commit 674e2af
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 19 deletions.
9 changes: 3 additions & 6 deletions src/pointer/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod _def {
use super::*;
/// The inner pointer stored inside a [`Ptr`][crate::Ptr].
///
/// `Ptr<'a, T>` is [covariant] in `'a` and `T`.
/// `PtrInner<'a, T>` is [covariant] in `'a` and invariant in `T`.
///
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
pub(crate) struct PtrInner<'a, T>
Expand All @@ -42,14 +42,11 @@ mod _def {
/// address space.
/// 5. If `ptr`'s referent is not zero sized,`A` is guaranteed to live
/// for at least `'a`.
// SAFETY: `NonNull<T>` is covariant over `T` [1].
//
// [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
ptr: NonNull<T>,
// SAFETY: `&'a T` is covariant over `'a` [1].
// SAFETY: `&'a mut T` is covariant in `'a` and invariant in `T` [1].
//
// [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance
_marker: PhantomData<&'a T>,
_marker: PhantomData<&'a mut T>,
}

impl<'a, T: 'a + ?Sized> Copy for PtrInner<'a, T> {}
Expand Down
8 changes: 0 additions & 8 deletions src/pointer/invariant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,6 @@ pub trait Aliasing: Sealed {
/// Is `Self` [`Exclusive`]?
#[doc(hidden)]
const IS_EXCLUSIVE: bool;

/// A type which has the correct variance over `'a` and `T` for this
/// aliasing invariant. `Ptr` stores a `<I::Aliasing as
/// Aliasing>::Variance<'a, T>` to inherit this variance.
#[doc(hidden)]
type Variance<'a, T: 'a + ?Sized>;
}

/// The alignment invariant of a [`Ptr`][super::Ptr].
Expand Down Expand Up @@ -132,7 +126,6 @@ impl<T: ?Sized> Validity for Uninit<T> {
pub enum Shared {}
impl Aliasing for Shared {
const IS_EXCLUSIVE: bool = false;
type Variance<'a, T: 'a + ?Sized> = &'a T;
}
impl Reference for Shared {}

Expand All @@ -144,7 +137,6 @@ impl Reference for Shared {}
pub enum Exclusive {}
impl Aliasing for Exclusive {
const IS_EXCLUSIVE: bool = true;
type Variance<'a, T: 'a + ?Sized> = &'a mut T;
}
impl Reference for Exclusive {}

Expand Down
9 changes: 4 additions & 5 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod def {
/// - `ptr` conforms to the alignment invariant of
/// [`I::Alignment`](invariant::Alignment).
///
/// `Ptr<'a, T>` is [covariant] in `'a` and `T`.
/// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`.
///
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
pub struct Ptr<'a, V, I>
Expand All @@ -54,9 +54,8 @@ mod def {
/// [`I::Aliasing`](invariant::Aliasing).
/// 2. `ptr` conforms to the alignment invariant of
/// [`I::Alignment`](invariant::Alignment).
// SAFETY: `PtrInner<'a, T>` is covariant over `'a` and `T`.
// SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`.
ptr: PtrInner<'a, V::Inner>,
_variance: PhantomData<<I::Aliasing as Aliasing>::Variance<'a, V::Inner>>,
_invariants: PhantomData<I>,
}

Expand Down Expand Up @@ -94,7 +93,7 @@ mod def {
let ptr = unsafe { PtrInner::new(ptr) };
// SAFETY: The caller has promised (in 6 - 8) to satisfy all safety
// invariants of `Ptr`.
Self { ptr, _variance: PhantomData, _invariants: PhantomData }
Self { ptr, _invariants: PhantomData }
}

/// Constructs a new `Ptr` from a [`PtrInner`].
Expand All @@ -112,7 +111,7 @@ mod def {
pub(super) const unsafe fn from_inner(ptr: PtrInner<'a, V::Inner>) -> Ptr<'a, V, I> {
// SAFETY: The caller has promised to satisfy all safety invariants
// of `Ptr`.
Self { ptr, _variance: PhantomData, _invariants: PhantomData }
Self { ptr, _invariants: PhantomData }
}

/// Converts this `Ptr<T>` to a [`PtrInner<T>`].
Expand Down

0 comments on commit 674e2af

Please sign in to comment.