@@ -42,11 +42,37 @@ pub struct CArc<T: ?Sized> {
42
42
43
43
/// The same as [`Self::stable_ref`] but it never changes.
44
44
#[ cfg( debug_assertions) ]
45
- base_stable_ref : NonNull < T > ,
45
+ base_stable_ref : StableRef < T > ,
46
46
47
- stable_ref : NonNull < T > ,
47
+ stable_ref : StableRef < T > ,
48
48
}
49
49
50
+ /// A stable reference, stored as a raw ptr.
51
+ ///
52
+ /// # Safety
53
+ ///
54
+ /// The raw ptr of a [`StableRef`] must have a stable address.
55
+ /// Even if `T`'s owning type, e.x. a [`Box`]`<T>`, is moved,
56
+ /// ptrs to `T` must remain valid and thus "stable".
57
+ ///
58
+ /// Thus, it can be stored relative to its owner.
59
+ #[ derive( Debug ) ]
60
+ struct StableRef < T : ?Sized > ( NonNull < T > ) ;
61
+
62
+ impl < T : ?Sized > Clone for StableRef < T > {
63
+ fn clone ( & self ) -> Self {
64
+ * self
65
+ }
66
+ }
67
+
68
+ impl < T : ?Sized > Copy for StableRef < T > { }
69
+
70
+ /// SAFETY: [`StableRef`]`<T>`, if it follows its safety guarantees, is essentially a `&T`/`&mut T`, which is [`Send`] if `T: `[`Send`]`.
71
+ unsafe impl < T : Send + ?Sized > Send for StableRef < T > { }
72
+
73
+ /// SAFETY: [`StableRef`]`<T>`, if it follows its safety guarantees, is essentially a `&T`/`&mut T`, which is [`Sync`] if `T: `[`Sync`].
74
+ unsafe impl < T : Send + ?Sized > Sync for StableRef < T > { }
75
+
50
76
impl < T : ?Sized > AsRef < T > for CArc < T > {
51
77
fn as_ref ( & self ) -> & T {
52
78
#[ cfg( debug_assertions) ]
@@ -57,12 +83,13 @@ impl<T: ?Sized> AsRef<T> for CArc<T> {
57
83
// Some extra checks to check if our ptrs are definitely invalid.
58
84
59
85
let real_ref = ( * self . owner ) . as_ref ( ) . get_ref ( ) ;
60
- assert_eq ! ( real_ref. to:: <NonNull <T >>( ) , self . base_stable_ref) ;
86
+ assert_eq ! ( real_ref. to:: <NonNull <T >>( ) , self . base_stable_ref. 0 ) ;
61
87
62
88
// Cast through `*const ()` and use [`pointer::byte_offset_from`]
63
89
// to remove any fat ptr metadata.
64
90
let offset = unsafe {
65
91
self . stable_ref
92
+ . 0
66
93
. as_ptr ( )
67
94
. cast :: < ( ) > ( )
68
95
. byte_offset_from ( ( real_ref as * const T ) . cast :: < ( ) > ( ) )
@@ -72,7 +99,7 @@ impl<T: ?Sized> AsRef<T> for CArc<T> {
72
99
let out_of_bounds = offset > len;
73
100
if out_of_bounds {
74
101
dbg ! ( real_ref as * const T ) ;
75
- dbg ! ( self . stable_ref. as_ptr( ) ) ;
102
+ dbg ! ( self . stable_ref. 0 . as_ptr( ) ) ;
76
103
dbg ! ( offset) ;
77
104
dbg ! ( len) ;
78
105
panic ! ( "CArc::stable_ref is out of bounds" ) ;
@@ -83,9 +110,9 @@ impl<T: ?Sized> AsRef<T> for CArc<T> {
83
110
// derived from [`Self::owner`]'s through [`CBox::as_ref`]
84
111
// and is thus safe to dereference.
85
112
// The [`CBox`] is [`Pin`]ned and
86
- // [`Self::stable_Ref `] is always updated on writes to [`Self::owner`],
113
+ // [`Self::stable_ref `] is always updated on writes to [`Self::owner`],
87
114
// so they are always in sync.
88
- unsafe { self . stable_ref . as_ref ( ) }
115
+ unsafe { self . stable_ref . 0 . as_ref ( ) }
89
116
}
90
117
}
91
118
@@ -116,7 +143,7 @@ impl<T: ?Sized> Clone for CArc<T> {
116
143
117
144
impl < T : ?Sized > From < Arc < Pin < CBox < T > > > > for CArc < T > {
118
145
fn from ( owner : Arc < Pin < CBox < T > > > ) -> Self {
119
- let stable_ref = ( * owner) . as_ref ( ) . get_ref ( ) . into ( ) ;
146
+ let stable_ref = StableRef ( ( * owner) . as_ref ( ) . get_ref ( ) . into ( ) ) ;
120
147
Self {
121
148
owner,
122
149
#[ cfg( debug_assertions) ]
@@ -229,7 +256,7 @@ impl<T> CArc<[T]> {
229
256
where
230
257
I : SliceIndex < [ T ] , Output = [ T ] > ,
231
258
{
232
- self . stable_ref = self . as_ref ( ) [ range] . into ( ) ;
259
+ self . stable_ref = StableRef ( self . as_ref ( ) [ range] . into ( ) ) ;
233
260
}
234
261
235
262
pub fn split_at ( this : Self , mid : usize ) -> ( Self , Self ) {
0 commit comments