Skip to content

Commit 978106f

Browse files
committed
[pointer] Support Box and Arc
gherrit-pr-id: I7fe90063e148d89e2f75b6fa63a960ad8b1dd432
1 parent 19f7378 commit 978106f

File tree

10 files changed

+261
-69
lines changed

10 files changed

+261
-69
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: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,7 @@ pub unsafe trait TryFromBytes {
13211321
/// [`UnsafeCell`]: core::cell::UnsafeCell
13221322
/// [`Shared`]: invariant::Shared
13231323
#[doc(hidden)]
1324-
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool;
1324+
fn is_bit_valid<A: invariant::ReadFoo>(candidate: Maybe<'_, Self, A>) -> bool;
13251325

13261326
/// Attempts to interpret the given `source` as a `&Self`.
13271327
///
@@ -3469,10 +3469,23 @@ pub unsafe trait FromBytes: FromZeros {
34693469
where
34703470
Self: KnownLayout + Immutable,
34713471
{
3472-
static_assert_dst_is_not_zst!(Self);
3473-
match Ptr::from_ref(source).try_cast_into_no_leftover::<_, BecauseImmutable>(None) {
3474-
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_ref()),
3475-
Err(err) => Err(err.map_src(|src| src.as_ref())),
3472+
Self::from_bytes(source)
3473+
}
3474+
3475+
#[must_use = "has no side effects"]
3476+
#[inline]
3477+
fn from_bytes<'a, P: pointer::Pointer<'a, Self>, R>(
3478+
source: P::To<'a, [u8]>,
3479+
) -> Result<P, CastError<P::To<'a, [u8]>, Self>>
3480+
where
3481+
R: invariant::ReadReason,
3482+
Self: 'a + KnownLayout + invariant::Read<P::Aliasing, R>,
3483+
{
3484+
match Ptr::<'_, _, (P::Aliasing, _, _)>::from_pointer(source)
3485+
.try_cast_into_no_leftover::<_, R>(None)
3486+
{
3487+
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().into_pointer()),
3488+
Err(err) => Err(err.map_src(|src| src.into_pointer())),
34763489
}
34773490
}
34783491

@@ -3705,11 +3718,7 @@ pub unsafe trait FromBytes: FromZeros {
37053718
where
37063719
Self: IntoBytes + KnownLayout,
37073720
{
3708-
static_assert_dst_is_not_zst!(Self);
3709-
match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) {
3710-
Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_mut()),
3711-
Err(err) => Err(err.map_src(|src| src.as_mut())),
3712-
}
3721+
Self::from_bytes(source)
37133722
}
37143723

37153724
/// 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: 101 additions & 34 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
@@ -295,8 +330,8 @@ impl ValidityInner for Valid {
295330
/// permitted to perform unsynchronized reads from its referent.
296331
pub trait Read<A: Aliasing, R: ReadReason> {}
297332

298-
impl<A: Reference, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
299-
impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {}
333+
impl<A: ReadFoo, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {}
334+
impl<A: ExclusiveFoo, T: ?Sized> Read<A, BecauseExclusive> for T {}
300335

301336
/// Used to disambiguate [`Read`] impls.
302337
pub trait ReadReason: Sealed {}
@@ -326,6 +361,10 @@ mod sealed {
326361
impl Sealed for Inaccessible {}
327362
impl Sealed for Shared {}
328363
impl Sealed for Exclusive {}
364+
#[cfg(feature = "alloc")]
365+
impl Sealed for Box {}
366+
#[cfg(feature = "std")]
367+
impl Sealed for Arc {}
329368

330369
impl Sealed for Aligned {}
331370

@@ -389,6 +428,10 @@ mod mapping {
389428
type FromInaccessible: Aliasing;
390429
type FromShared: Aliasing;
391430
type FromExclusive: Aliasing;
431+
#[cfg(feature = "alloc")]
432+
type FromBox: Aliasing;
433+
#[cfg(feature = "std")]
434+
type FromArc: Aliasing;
392435
}
393436

394437
/// A mapping from one [`Alignment`] type to another.
@@ -457,12 +500,20 @@ mod mapping {
457500
type FromInaccessible = FromInaccessible;
458501
type FromShared = FromShared;
459502
type FromExclusive = FromExclusive;
503+
#[cfg(feature = "alloc")]
504+
type FromBox = Inaccessible;
505+
#[cfg(feature = "std")]
506+
type FromArc = Inaccessible;
460507
}
461508

462509
impl AliasingMapping for Inaccessible {
463510
type FromInaccessible = Inaccessible;
464511
type FromShared = Inaccessible;
465512
type FromExclusive = Inaccessible;
513+
#[cfg(feature = "alloc")]
514+
type FromBox = Inaccessible;
515+
#[cfg(feature = "std")]
516+
type FromArc = Inaccessible;
466517
}
467518

468519
pub enum UnsafeCellMismatch {}
@@ -471,24 +522,40 @@ mod mapping {
471522
type FromInaccessible = Inaccessible;
472523
type FromShared = Inaccessible;
473524
type FromExclusive = Exclusive;
525+
#[cfg(feature = "alloc")]
526+
type FromBox = Box;
527+
#[cfg(feature = "std")]
528+
type FromArc = Inaccessible;
474529
}
475530

476531
impl AliasingMapping for Preserved {
477532
type FromInaccessible = Inaccessible;
478533
type FromShared = Shared;
479534
type FromExclusive = Exclusive;
535+
#[cfg(feature = "alloc")]
536+
type FromBox = Box;
537+
#[cfg(feature = "std")]
538+
type FromArc = Arc;
480539
}
481540

482541
impl AliasingMapping for Shared {
483542
type FromInaccessible = Shared;
484543
type FromShared = Shared;
485544
type FromExclusive = Shared;
545+
#[cfg(feature = "alloc")]
546+
type FromBox = Shared;
547+
#[cfg(feature = "std")]
548+
type FromArc = Shared;
486549
}
487550

488551
impl AliasingMapping for Exclusive {
489552
type FromInaccessible = Exclusive;
490553
type FromShared = Exclusive;
491554
type FromExclusive = Exclusive;
555+
#[cfg(feature = "alloc")]
556+
type FromBox = Exclusive;
557+
#[cfg(feature = "std")]
558+
type FromArc = Exclusive;
492559
}
493560

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

0 commit comments

Comments
 (0)