Skip to content

Commit 343cfbc

Browse files
committed
[pointer] Support Box and Arc
gherrit-pr-id: I7fe90063e148d89e2f75b6fa63a960ad8b1dd432
1 parent af10d3d commit 343cfbc

File tree

10 files changed

+232
-70
lines changed

10 files changed

+232
-70
lines changed

src/impls.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
648648
}
649649

650650
#[inline]
651-
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool {
651+
fn is_bit_valid<A: invariant::ReadFoo>(candidate: Maybe<'_, Self, A>) -> bool {
652652
// The only way to implement this function is using an exclusive-aliased
653653
// pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
654654
// (other than by using `unsafe` code, which we can't use since we can't
@@ -1124,15 +1124,15 @@ mod tests {
11241124

11251125
pub(super) trait TestIsBitValidShared<T: ?Sized> {
11261126
#[allow(clippy::needless_lifetimes)]
1127-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1127+
fn test_is_bit_valid_shared<'ptr, A: invariant::ReadFoo>(
11281128
&self,
11291129
candidate: Maybe<'ptr, T, A>,
11301130
) -> Option<bool>;
11311131
}
11321132

11331133
impl<T: TryFromBytes + Immutable + ?Sized> TestIsBitValidShared<T> for AutorefWrapper<T> {
11341134
#[allow(clippy::needless_lifetimes)]
1135-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1135+
fn test_is_bit_valid_shared<'ptr, A: invariant::ReadFoo>(
11361136
&self,
11371137
candidate: Maybe<'ptr, T, A>,
11381138
) -> Option<bool> {
@@ -1222,7 +1222,7 @@ mod tests {
12221222
#[allow(unused, non_local_definitions)]
12231223
impl AutorefWrapper<$ty> {
12241224
#[allow(clippy::needless_lifetimes)]
1225-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1225+
fn test_is_bit_valid_shared<'ptr, A: invariant::ReadFoo>(
12261226
&mut self,
12271227
candidate: Maybe<'ptr, $ty, A>,
12281228
) -> Option<bool> {

src/lib.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ pub unsafe trait TryFromBytes {
13201320
/// [`UnsafeCell`]: core::cell::UnsafeCell
13211321
/// [`Shared`]: invariant::Shared
13221322
#[doc(hidden)]
1323-
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool;
1323+
fn is_bit_valid<A: invariant::ReadFoo>(candidate: Maybe<'_, Self, A>) -> bool;
13241324

13251325
/// Attempts to interpret the given `source` as a `&Self`.
13261326
///
@@ -3458,10 +3458,22 @@ pub unsafe trait FromBytes: FromZeros {
34583458
where
34593459
Self: KnownLayout + Immutable,
34603460
{
3461-
static_assert_dst_is_not_zst!(Self);
3462-
match Ptr::from_ref(source).try_cast_into_no_leftover::<_, BecauseImmutable>(None) {
3463-
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_ref()),
3464-
Err(err) => Err(err.map_src(|src| src.as_ref())),
3461+
Self::from_bytes(source)
3462+
}
3463+
3464+
#[must_use = "has no side effects"]
3465+
#[inline]
3466+
fn from_bytes<'a, P: pointer::Pointer<'a, Self>, R>(
3467+
source: P::To<'a, [u8]>,
3468+
) -> Result<P, CastError<P::To<'a, [u8]>, Self>>
3469+
where
3470+
Self: 'a + KnownLayout + invariant::Read<P::Aliasing, R>,
3471+
{
3472+
match Ptr::<'_, _, (P::Aliasing, _, _)>::from_pointer(source)
3473+
.try_cast_into_no_leftover::<_, R>(None)
3474+
{
3475+
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().into_pointer()),
3476+
Err(err) => Err(err.map_src(|src| src.into_pointer())),
34653477
}
34663478
}
34673479

@@ -3694,11 +3706,7 @@ pub unsafe trait FromBytes: FromZeros {
36943706
where
36953707
Self: IntoBytes + KnownLayout,
36963708
{
3697-
static_assert_dst_is_not_zst!(Self);
3698-
match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) {
3699-
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_mut()),
3700-
Err(err) => Err(err.map_src(|src| src.as_mut())),
3701-
}
3709+
Self::from_bytes(source)
37023710
}
37033711

37043712
/// Interprets the prefix of the given `source` as a `&mut Self` without

src/pointer/inner.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ mod _def {
2525
/// `Ptr<'a, T>` is [covariant] in `'a` and `T`.
2626
///
2727
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
28-
pub(crate) struct PtrInner<'a, T>
28+
#[allow(missing_debug_implementations)]
29+
pub struct PtrInner<'a, T>
2930
where
3031
T: ?Sized,
3132
{

src/pointer/invariant.rs

Lines changed: 73 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
//! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`])
1414
//! triples implementing the [`Invariants`] trait.
1515
16-
use super::*;
17-
1816
/// The invariants of a [`Ptr`][super::Ptr].
1917
pub trait Invariants: Sealed {
2018
type Aliasing: Aliasing;
@@ -82,6 +80,15 @@ pub trait Aliasing:
8280
/// Aliasing>::Variance<'a, T>` to inherit this variance.
8381
#[doc(hidden)]
8482
type Variance<'a, T: 'a + ?Sized>;
83+
84+
// #[doc(hidden)]
85+
// type Applied<'a, T: 'a + ?Sized>;
86+
87+
// #[doc(hidden)]
88+
// fn into_ptr<'a, T: 'a + ?Sized>(ptr: Self::Applied<'a, T>) -> PtrInner<'a, T>;
89+
90+
// #[doc(hidden)]
91+
// unsafe fn from_ptr<'a, T: 'a + ?Sized>(ptr: PtrInner<'a, T>) -> Self::Applied<'a, T>;
8592
}
8693

8794
#[doc(hidden)]
@@ -136,14 +143,7 @@ impl<
136143
///
137144
/// Given `A: Reference`, callers may assume that either `A = Shared` or `A =
138145
/// Exclusive`.
139-
pub trait Reference: Aliasing + Sealed {
140-
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, shared: S, exclusive: E) -> O
141-
where
142-
T: 'a + ?Sized,
143-
I: Invariants<Aliasing = Self>,
144-
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
145-
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O;
146-
}
146+
pub trait Reference: ReadFoo + Sealed {}
147147

148148
/// It is unknown whether any invariant holds.
149149
pub enum Unknown {}
@@ -171,18 +171,7 @@ impl Aliasing for Shared {
171171
const IS_EXCLUSIVE: bool = false;
172172
type Variance<'a, T: 'a + ?Sized> = &'a T;
173173
}
174-
impl Reference for Shared {
175-
#[inline(always)]
176-
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, shared: S, _exclusive: E) -> O
177-
where
178-
T: 'a + ?Sized,
179-
I: Invariants<Aliasing = Shared>,
180-
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
181-
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
182-
{
183-
shared(ptr.unify_invariants())
184-
}
185-
}
174+
impl Reference for Shared {}
186175

187176
/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`.
188177
///
@@ -197,16 +186,41 @@ impl Aliasing for Exclusive {
197186
const IS_EXCLUSIVE: bool = true;
198187
type Variance<'a, T: 'a + ?Sized> = &'a mut T;
199188
}
200-
impl Reference for Exclusive {
201-
#[inline(always)]
202-
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, _shared: S, exclusive: E) -> O
203-
where
204-
T: 'a + ?Sized,
205-
I: Invariants<Aliasing = Exclusive>,
206-
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
207-
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
208-
{
209-
exclusive(ptr.unify_invariants())
189+
impl Reference for Exclusive {}
190+
191+
#[cfg(feature = "alloc")]
192+
pub use _alloc::*;
193+
#[cfg(feature = "alloc")]
194+
mod _alloc {
195+
use alloc::boxed::Box as Bx;
196+
197+
use super::*;
198+
199+
pub enum Box {}
200+
impl AliasingInner for Box {
201+
// type MappedTo<M: AliasingMapping> = M::FromBox;
202+
}
203+
impl Aliasing for Box {
204+
const IS_EXCLUSIVE: bool = true;
205+
type Variance<'a, T: 'a + ?Sized> = Bx<T>;
206+
}
207+
}
208+
209+
#[cfg(feature = "std")]
210+
pub use _std::*;
211+
#[cfg(feature = "std")]
212+
mod _std {
213+
use std::sync::Arc as Ac;
214+
215+
use super::*;
216+
217+
pub enum Arc {}
218+
impl AliasingInner for Arc {
219+
// type MappedTo<M: AliasingMapping> = M::FromArc;
220+
}
221+
impl Aliasing for Arc {
222+
const IS_EXCLUSIVE: bool = true;
223+
type Variance<'a, T: 'a + ?Sized> = Ac<T>;
210224
}
211225
}
212226

@@ -261,6 +275,27 @@ impl ValidityInner for Valid {
261275
type MappedTo<M: ValidityMapping> = M::FromValid;
262276
}
263277

278+
// Aliasing modes that permit reading at all (ie, everything but Inaccessible).
279+
pub trait ReadFoo: Aliasing {}
280+
impl ReadFoo for Shared {}
281+
impl ReadFoo for Exclusive {}
282+
#[cfg(feature = "alloc")]
283+
impl ReadFoo for Box {}
284+
#[cfg(feature = "std")]
285+
impl ReadFoo for Arc {}
286+
287+
// Shared, Arc, etc
288+
pub trait SharedFoo: Aliasing {}
289+
impl SharedFoo for Shared {}
290+
#[cfg(feature = "std")]
291+
impl SharedFoo for Arc {}
292+
293+
// Exclusive, Box, etc
294+
pub trait ExclusiveFoo: Aliasing {}
295+
impl ExclusiveFoo for Exclusive {}
296+
#[cfg(feature = "alloc")]
297+
impl ExclusiveFoo for Box {}
298+
264299
/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
265300
///
266301
/// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits
@@ -285,8 +320,7 @@ define_because!(
285320
#[doc(hidden)]
286321
pub BecauseExclusive
287322
);
288-
// SAFETY: The aliasing parameter is `Exclusive`.
289-
unsafe impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {}
323+
unsafe impl<A: ExclusiveFoo, T: ?Sized> Read<A, BecauseExclusive> for T {}
290324

291325
define_because!(
292326
/// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s
@@ -295,7 +329,7 @@ define_because!(
295329
pub BecauseImmutable
296330
);
297331
// SAFETY: `T: Immutable`.
298-
unsafe impl<A: Reference, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
332+
unsafe impl<A: ReadFoo, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
299333

300334
use sealed::Sealed;
301335
mod sealed {
@@ -308,6 +342,10 @@ mod sealed {
308342
// impl Sealed for Inaccessible {}
309343
impl Sealed for Shared {}
310344
impl Sealed for Exclusive {}
345+
#[cfg(feature = "alloc")]
346+
impl Sealed for Box {}
347+
#[cfg(feature = "std")]
348+
impl Sealed for Arc {}
311349

312350
impl Sealed for Aligned {}
313351

src/pointer/mod.rs

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ where
6161
impl<'a, T, Aliasing, Alignment> MaybeAligned<'a, T, Aliasing, Alignment>
6262
where
6363
T: 'a + ?Sized,
64-
Aliasing: invariant::Reference,
64+
Aliasing: invariant::ReadFoo,
6565
Alignment: invariant::Alignment,
6666
{
6767
/// Views the value as an aligned reference.
@@ -82,7 +82,96 @@ pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool
8282
where
8383
T: crate::Immutable + crate::KnownLayout,
8484
I: invariant::Invariants<Validity = invariant::Initialized>,
85-
I::Aliasing: invariant::Reference,
85+
I::Aliasing: invariant::ReadFoo,
8686
{
8787
ptr.as_bytes::<BecauseImmutable>().as_ref().iter().all(|&byte| byte == 0)
8888
}
89+
90+
pub use _pointer::*;
91+
mod _pointer {
92+
#[cfg(feature = "alloc")]
93+
use alloc::boxed::Box;
94+
#[cfg(feature = "std")]
95+
use std::sync::Arc;
96+
97+
use super::{inner::PtrInner, invariant::*};
98+
99+
pub unsafe trait Pointer<'t, T: ?Sized> {
100+
type To<'u, U: 'u + ?Sized>: Pointer<'u, U, Aliasing = Self::Aliasing>;
101+
102+
#[doc(hidden)]
103+
type Aliasing: ReadFoo + Aliasing;
104+
105+
#[doc(hidden)]
106+
fn into_ptr(self) -> PtrInner<'t, T>;
107+
108+
#[doc(hidden)]
109+
unsafe fn from_ptr(ptr: PtrInner<'t, T>) -> Self;
110+
}
111+
112+
unsafe impl<'t, T: ?Sized> Pointer<'t, T> for &'t T {
113+
type To<'u, U: 'u + ?Sized> = &'u U;
114+
115+
type Aliasing = Shared;
116+
117+
#[inline(always)]
118+
fn into_ptr(self) -> PtrInner<'t, T> {
119+
PtrInner::from_ref(self)
120+
}
121+
122+
#[inline(always)]
123+
unsafe fn from_ptr(ptr: PtrInner<'t, T>) -> Self {
124+
unsafe { ptr.as_non_null().as_ref() }
125+
}
126+
}
127+
128+
unsafe impl<'t, T: ?Sized> Pointer<'t, T> for &'t mut T {
129+
type To<'u, U: 'u + ?Sized> = &'u mut U;
130+
131+
type Aliasing = Exclusive;
132+
133+
#[inline(always)]
134+
fn into_ptr(self) -> PtrInner<'t, T> {
135+
PtrInner::from_ref(self)
136+
}
137+
138+
#[inline(always)]
139+
unsafe fn from_ptr(ptr: PtrInner<'t, T>) -> Self {
140+
unsafe { ptr.as_non_null().as_mut() }
141+
}
142+
}
143+
144+
#[cfg(feature = "alloc")]
145+
unsafe impl<'t, T: ?Sized> Pointer<'t, T> for Box<T> {
146+
type To<'u, U: 'u + ?Sized> = Box<U>;
147+
148+
type Aliasing = super::invariant::Box;
149+
150+
#[inline(always)]
151+
fn into_ptr(self) -> PtrInner<'t, T> {
152+
PtrInner::from_box(self)
153+
}
154+
155+
#[inline(always)]
156+
unsafe fn from_ptr(ptr: PtrInner<'t, T>) -> Box<T> {
157+
unsafe { Box::from_raw(ptr.as_non_null().as_ptr()) }
158+
}
159+
}
160+
161+
#[cfg(feature = "std")]
162+
unsafe impl<'t, T: ?Sized> Pointer<'t, T> for Arc<T> {
163+
type To<'u, U: 'u + ?Sized> = Arc<U>;
164+
165+
type Aliasing = super::invariant::Arc;
166+
167+
#[inline(always)]
168+
fn into_ptr(self) -> PtrInner<'t, T> {
169+
PtrInner::from_arc(self)
170+
}
171+
172+
#[inline(always)]
173+
unsafe fn from_ptr(ptr: PtrInner<'t, T>) -> Arc<T> {
174+
unsafe { Arc::from_raw(ptr.as_non_null().as_ptr()) }
175+
}
176+
}
177+
}

0 commit comments

Comments
 (0)