Skip to content

Commit 281cd32

Browse files
committed
[pointer] Support Box and Arc
gherrit-pr-id: I7fe90063e148d89e2f75b6fa63a960ad8b1dd432
1 parent 90c2f64 commit 281cd32

File tree

10 files changed

+261
-71
lines changed

10 files changed

+261
-71
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: 102 additions & 36 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 {}
@@ -189,18 +189,7 @@ impl Aliasing for Shared {
189189
const IS_EXCLUSIVE: bool = false;
190190
type Variance<'a, T: 'a + ?Sized> = &'a T;
191191
}
192-
impl Reference for Shared {
193-
#[inline(always)]
194-
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, shared: S, _exclusive: E) -> O
195-
where
196-
T: 'a + ?Sized,
197-
I: Invariants<Aliasing = Shared>,
198-
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
199-
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
200-
{
201-
shared(ptr.unify_invariants())
202-
}
203-
}
192+
impl Reference for Shared {}
204193

205194
/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`.
206195
///
@@ -215,16 +204,41 @@ impl Aliasing for Exclusive {
215204
const IS_EXCLUSIVE: bool = true;
216205
type Variance<'a, T: 'a + ?Sized> = &'a mut T;
217206
}
218-
impl Reference for Exclusive {
219-
#[inline(always)]
220-
fn with<'a, T, I, S, E, O>(ptr: Ptr<'a, T, I>, _shared: S, exclusive: E) -> O
221-
where
222-
T: 'a + ?Sized,
223-
I: Invariants<Aliasing = Exclusive>,
224-
S: FnOnce(Ptr<'a, T, I::WithAliasing<Shared>>) -> O,
225-
E: FnOnce(Ptr<'a, T, I::WithAliasing<Exclusive>>) -> O,
226-
{
227-
exclusive(ptr.unify_invariants())
207+
impl Reference for Exclusive {}
208+
209+
#[cfg(feature = "alloc")]
210+
pub use _alloc::*;
211+
#[cfg(feature = "alloc")]
212+
mod _alloc {
213+
use alloc::boxed::Box as Bx;
214+
215+
use super::*;
216+
217+
pub enum Box {}
218+
impl AliasingInner for Box {
219+
// type MappedTo<M: AliasingMapping> = M::FromBox;
220+
}
221+
impl Aliasing for Box {
222+
const IS_EXCLUSIVE: bool = true;
223+
type Variance<'a, T: 'a + ?Sized> = Bx<T>;
224+
}
225+
}
226+
227+
#[cfg(feature = "std")]
228+
pub use _std::*;
229+
#[cfg(feature = "std")]
230+
mod _std {
231+
use std::sync::Arc as Ac;
232+
233+
use super::*;
234+
235+
pub enum Arc {}
236+
impl AliasingInner for Arc {
237+
// type MappedTo<M: AliasingMapping> = M::FromArc;
238+
}
239+
impl Aliasing for Arc {
240+
const IS_EXCLUSIVE: bool = true;
241+
type Variance<'a, T: 'a + ?Sized> = Ac<T>;
228242
}
229243
}
230244

@@ -279,6 +293,27 @@ impl ValidityInner for Valid {
279293
type MappedTo<M: ValidityMapping> = M::FromValid;
280294
}
281295

296+
// Aliasing modes that permit reading at all (ie, everything but Inaccessible).
297+
pub trait ReadFoo: Aliasing {}
298+
impl ReadFoo for Shared {}
299+
impl ReadFoo for Exclusive {}
300+
#[cfg(feature = "alloc")]
301+
impl ReadFoo for Box {}
302+
#[cfg(feature = "std")]
303+
impl ReadFoo for Arc {}
304+
305+
// Shared, Arc, etc
306+
pub trait SharedFoo: Aliasing {}
307+
impl SharedFoo for Shared {}
308+
#[cfg(feature = "std")]
309+
impl SharedFoo for Arc {}
310+
311+
// Exclusive, Box, etc
312+
pub trait ExclusiveFoo: Aliasing {}
313+
impl ExclusiveFoo for Exclusive {}
314+
#[cfg(feature = "alloc")]
315+
impl ExclusiveFoo for Box {}
316+
282317
/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
283318
///
284319
/// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits
@@ -303,8 +338,7 @@ define_because!(
303338
#[doc(hidden)]
304339
pub BecauseExclusive
305340
);
306-
// SAFETY: The aliasing parameter is `Exclusive`.
307-
unsafe impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {}
341+
unsafe impl<A: ExclusiveFoo, T: ?Sized> Read<A, BecauseExclusive> for T {}
308342

309343
define_because!(
310344
/// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s
@@ -313,7 +347,7 @@ define_because!(
313347
pub BecauseImmutable
314348
);
315349
// SAFETY: `T: Immutable`.
316-
unsafe impl<A: Reference, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
350+
unsafe impl<A: ReadFoo, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
317351

318352
use sealed::Sealed;
319353
mod sealed {
@@ -326,6 +360,10 @@ mod sealed {
326360
// impl Sealed for Inaccessible {}
327361
impl Sealed for Shared {}
328362
impl Sealed for Exclusive {}
363+
#[cfg(feature = "alloc")]
364+
impl Sealed for Box {}
365+
#[cfg(feature = "std")]
366+
impl Sealed for Arc {}
329367

330368
impl Sealed for Aligned {}
331369

@@ -386,6 +424,10 @@ mod mapping {
386424
// type FromInaccessible: Aliasing;
387425
type FromShared: Aliasing;
388426
type FromExclusive: Aliasing;
427+
#[cfg(feature = "alloc")]
428+
type FromBox: Aliasing;
429+
#[cfg(feature = "std")]
430+
type FromArc: Aliasing;
389431
}
390432

391433
/// A mapping from one [`Alignment`] type to another.
@@ -454,38 +496,62 @@ mod mapping {
454496
// // type FromInaccessible = FromInaccessible;
455497
// type FromShared = FromShared;
456498
// type FromExclusive = FromExclusive;
499+
// #[cfg(feature = "alloc")]
500+
// type FromBox = Inaccessible;
501+
// #[cfg(feature = "std")]
502+
// type FromArc = Inaccessible;
457503
// }
458504

459505
// impl AliasingMapping for Inaccessible {
460506
// type FromInaccessible = Inaccessible;
461507
// type FromShared = Inaccessible;
462508
// type FromExclusive = Inaccessible;
509+
// #[cfg(feature = "alloc")]
510+
// type FromBox = Inaccessible;
511+
// #[cfg(feature = "std")]
512+
// type FromArc = Inaccessible;
463513
// }
464514

465515
// pub enum UnsafeCellMismatch {}
466516

467517
// impl AliasingMapping for UnsafeCellMismatch {
468-
// // type FromInaccessible = Inaccessible;
518+
// type FromInaccessible = Inaccessible;
469519
// type FromShared = Inaccessible;
470520
// type FromExclusive = Exclusive;
521+
// #[cfg(feature = "alloc")]
522+
// type FromBox = Box;
523+
// #[cfg(feature = "std")]
524+
// type FromArc = Inaccessible;
471525
// }
472526

473527
// impl AliasingMapping for Preserved {
474528
// // type FromInaccessible = Inaccessible;
475529
// type FromShared = Shared;
476530
// type FromExclusive = Exclusive;
531+
// #[cfg(feature = "alloc")]
532+
// type FromBox = Box;
533+
// #[cfg(feature = "std")]
534+
// type FromArc = Arc;
477535
// }
478536

479537
// impl AliasingMapping for Shared {
480538
// // type FromInaccessible = Shared;
481539
// type FromShared = Shared;
482540
// type FromExclusive = Shared;
541+
// #[cfg(feature = "alloc")]
542+
// type FromBox = Shared;
543+
// #[cfg(feature = "std")]
544+
// type FromArc = Shared;
483545
// }
484546

485547
// impl AliasingMapping for Exclusive {
486548
// // type FromInaccessible = Exclusive;
487549
// type FromShared = Exclusive;
488550
// type FromExclusive = Exclusive;
551+
// #[cfg(feature = "alloc")]
552+
// type FromBox = Exclusive;
553+
// #[cfg(feature = "std")]
554+
// type FromArc = Exclusive;
489555
// }
490556

491557
impl<FromUnknown: Alignment, FromAligned: Alignment> AlignmentMapping

0 commit comments

Comments
 (0)