6
6
//! structure's APIs are `unsafe` as they require the caller to ensure the
7
7
//! specified node is actually contained by the list.
8
8
9
+ use core:: cell:: UnsafeCell ;
9
10
use core:: fmt;
10
- use core:: marker:: PhantomData ;
11
+ use core:: marker:: { PhantomData , PhantomPinned } ;
11
12
use core:: mem:: ManuallyDrop ;
12
- use core:: ptr:: NonNull ;
13
+ use core:: ptr:: { self , NonNull } ;
13
14
14
15
/// An intrusive linked list.
15
16
///
@@ -60,11 +61,40 @@ pub(crate) unsafe trait Link {
60
61
61
62
/// Previous / next pointers
62
63
pub ( crate ) struct Pointers < T > {
64
+ inner : UnsafeCell < PointersInner < T > > ,
65
+ }
66
+ /// We do not want the compiler to put the `noalias` attribute on mutable
67
+ /// references to this type, so the type has been made `!Unpin` with a
68
+ /// `PhantomPinned` field.
69
+ ///
70
+ /// Additionally, we never access the `prev` or `next` fields directly, as any
71
+ /// such access would implicitly involve the creation of a reference to the
72
+ /// field, which we want to avoid since the fields are not `!Unpin`, and would
73
+ /// hence be given the `noalias` attribute if we were to do such an access.
74
+ /// As an alternative to accessing the fields directly, the `Pointers` type
75
+ /// provides getters and setters for the two fields, and those are implemented
76
+ /// using raw pointer casts and offsets, which is valid since the struct is
77
+ /// #[repr(C)].
78
+ ///
79
+ /// See this link for more information:
80
+ /// https://github.com/rust-lang/rust/pull/82834
81
+ #[ repr( C ) ]
82
+ struct PointersInner < T > {
63
83
/// The previous node in the list. null if there is no previous node.
84
+ ///
85
+ /// This field is accessed through pointer manipulation, so it is not dead code.
86
+ #[ allow( dead_code) ]
64
87
prev : Option < NonNull < T > > ,
65
88
66
89
/// The next node in the list. null if there is no previous node.
90
+ ///
91
+ /// This field is accessed through pointer manipulation, so it is not dead code.
92
+ #[ allow( dead_code) ]
67
93
next : Option < NonNull < T > > ,
94
+
95
+ /// This type is !Unpin due to the heuristic from:
96
+ /// https://github.com/rust-lang/rust/pull/82834
97
+ _pin : PhantomPinned ,
68
98
}
69
99
70
100
unsafe impl < T : Send > Send for Pointers < T > { }
@@ -91,11 +121,11 @@ impl<L: Link> LinkedList<L, L::Target> {
91
121
let ptr = L :: as_raw ( & * val) ;
92
122
assert_ne ! ( self . head, Some ( ptr) ) ;
93
123
unsafe {
94
- L :: pointers ( ptr) . as_mut ( ) . next = self . head ;
95
- L :: pointers ( ptr) . as_mut ( ) . prev = None ;
124
+ L :: pointers ( ptr) . as_mut ( ) . set_next ( self . head ) ;
125
+ L :: pointers ( ptr) . as_mut ( ) . set_prev ( None ) ;
96
126
97
127
if let Some ( head) = self . head {
98
- L :: pointers ( head) . as_mut ( ) . prev = Some ( ptr) ;
128
+ L :: pointers ( head) . as_mut ( ) . set_prev ( Some ( ptr) ) ;
99
129
}
100
130
101
131
self . head = Some ( ptr) ;
@@ -111,16 +141,16 @@ impl<L: Link> LinkedList<L, L::Target> {
111
141
pub ( crate ) fn pop_back ( & mut self ) -> Option < L :: Handle > {
112
142
unsafe {
113
143
let last = self . tail ?;
114
- self . tail = L :: pointers ( last) . as_ref ( ) . prev ;
144
+ self . tail = L :: pointers ( last) . as_ref ( ) . get_prev ( ) ;
115
145
116
- if let Some ( prev) = L :: pointers ( last) . as_ref ( ) . prev {
117
- L :: pointers ( prev) . as_mut ( ) . next = None ;
146
+ if let Some ( prev) = L :: pointers ( last) . as_ref ( ) . get_prev ( ) {
147
+ L :: pointers ( prev) . as_mut ( ) . set_next ( None ) ;
118
148
} else {
119
149
self . head = None
120
150
}
121
151
122
- L :: pointers ( last) . as_mut ( ) . prev = None ;
123
- L :: pointers ( last) . as_mut ( ) . next = None ;
152
+ L :: pointers ( last) . as_mut ( ) . set_prev ( None ) ;
153
+ L :: pointers ( last) . as_mut ( ) . set_next ( None ) ;
124
154
125
155
Some ( L :: from_raw ( last) )
126
156
}
@@ -143,31 +173,35 @@ impl<L: Link> LinkedList<L, L::Target> {
143
173
/// The caller **must** ensure that `node` is currently contained by
144
174
/// `self` or not contained by any other list.
145
175
pub ( crate ) unsafe fn remove ( & mut self , node : NonNull < L :: Target > ) -> Option < L :: Handle > {
146
- if let Some ( prev) = L :: pointers ( node) . as_ref ( ) . prev {
147
- debug_assert_eq ! ( L :: pointers( prev) . as_ref( ) . next, Some ( node) ) ;
148
- L :: pointers ( prev) . as_mut ( ) . next = L :: pointers ( node) . as_ref ( ) . next ;
176
+ if let Some ( prev) = L :: pointers ( node) . as_ref ( ) . get_prev ( ) {
177
+ debug_assert_eq ! ( L :: pointers( prev) . as_ref( ) . get_next( ) , Some ( node) ) ;
178
+ L :: pointers ( prev)
179
+ . as_mut ( )
180
+ . set_next ( L :: pointers ( node) . as_ref ( ) . get_next ( ) ) ;
149
181
} else {
150
182
if self . head != Some ( node) {
151
183
return None ;
152
184
}
153
185
154
- self . head = L :: pointers ( node) . as_ref ( ) . next ;
186
+ self . head = L :: pointers ( node) . as_ref ( ) . get_next ( ) ;
155
187
}
156
188
157
- if let Some ( next) = L :: pointers ( node) . as_ref ( ) . next {
158
- debug_assert_eq ! ( L :: pointers( next) . as_ref( ) . prev, Some ( node) ) ;
159
- L :: pointers ( next) . as_mut ( ) . prev = L :: pointers ( node) . as_ref ( ) . prev ;
189
+ if let Some ( next) = L :: pointers ( node) . as_ref ( ) . get_next ( ) {
190
+ debug_assert_eq ! ( L :: pointers( next) . as_ref( ) . get_prev( ) , Some ( node) ) ;
191
+ L :: pointers ( next)
192
+ . as_mut ( )
193
+ . set_prev ( L :: pointers ( node) . as_ref ( ) . get_prev ( ) ) ;
160
194
} else {
161
195
// This might be the last item in the list
162
196
if self . tail != Some ( node) {
163
197
return None ;
164
198
}
165
199
166
- self . tail = L :: pointers ( node) . as_ref ( ) . prev ;
200
+ self . tail = L :: pointers ( node) . as_ref ( ) . get_prev ( ) ;
167
201
}
168
202
169
- L :: pointers ( node) . as_mut ( ) . next = None ;
170
- L :: pointers ( node) . as_mut ( ) . prev = None ;
203
+ L :: pointers ( node) . as_mut ( ) . set_next ( None ) ;
204
+ L :: pointers ( node) . as_mut ( ) . set_prev ( None ) ;
171
205
172
206
Some ( L :: from_raw ( node) )
173
207
}
@@ -224,7 +258,7 @@ cfg_rt_multi_thread! {
224
258
fn next( & mut self ) -> Option <& ' a T :: Target > {
225
259
let curr = self . curr?;
226
260
// safety: the pointer references data contained by the list
227
- self . curr = unsafe { T :: pointers( curr) . as_ref( ) } . next ;
261
+ self . curr = unsafe { T :: pointers( curr) . as_ref( ) } . get_next ( ) ;
228
262
229
263
// safety: the value is still owned by the linked list.
230
264
Some ( unsafe { & * curr. as_ptr( ) } )
@@ -265,7 +299,7 @@ cfg_io_readiness! {
265
299
fn next( & mut self ) -> Option <Self :: Item > {
266
300
while let Some ( curr) = self . curr {
267
301
// safety: the pointer references data contained by the list
268
- self . curr = unsafe { T :: pointers( curr) . as_ref( ) } . next ;
302
+ self . curr = unsafe { T :: pointers( curr) . as_ref( ) } . get_next ( ) ;
269
303
270
304
// safety: the value is still owned by the linked list.
271
305
if ( self . filter) ( unsafe { & mut * curr. as_ptr( ) } ) {
@@ -284,17 +318,58 @@ impl<T> Pointers<T> {
284
318
/// Create a new set of empty pointers
285
319
pub ( crate ) fn new ( ) -> Pointers < T > {
286
320
Pointers {
287
- prev : None ,
288
- next : None ,
321
+ inner : UnsafeCell :: new ( PointersInner {
322
+ prev : None ,
323
+ next : None ,
324
+ _pin : PhantomPinned ,
325
+ } ) ,
326
+ }
327
+ }
328
+
329
+ fn get_prev ( & self ) -> Option < NonNull < T > > {
330
+ // SAFETY: prev is the first field in PointersInner, which is #[repr(C)].
331
+ unsafe {
332
+ let inner = self . inner . get ( ) ;
333
+ let prev = inner as * const Option < NonNull < T > > ;
334
+ ptr:: read ( prev)
335
+ }
336
+ }
337
+ fn get_next ( & self ) -> Option < NonNull < T > > {
338
+ // SAFETY: next is the second field in PointersInner, which is #[repr(C)].
339
+ unsafe {
340
+ let inner = self . inner . get ( ) ;
341
+ let prev = inner as * const Option < NonNull < T > > ;
342
+ let next = prev. add ( 1 ) ;
343
+ ptr:: read ( next)
344
+ }
345
+ }
346
+
347
+ fn set_prev ( & mut self , value : Option < NonNull < T > > ) {
348
+ // SAFETY: prev is the first field in PointersInner, which is #[repr(C)].
349
+ unsafe {
350
+ let inner = self . inner . get ( ) ;
351
+ let prev = inner as * mut Option < NonNull < T > > ;
352
+ ptr:: write ( prev, value) ;
353
+ }
354
+ }
355
+ fn set_next ( & mut self , value : Option < NonNull < T > > ) {
356
+ // SAFETY: next is the second field in PointersInner, which is #[repr(C)].
357
+ unsafe {
358
+ let inner = self . inner . get ( ) ;
359
+ let prev = inner as * mut Option < NonNull < T > > ;
360
+ let next = prev. add ( 1 ) ;
361
+ ptr:: write ( next, value) ;
289
362
}
290
363
}
291
364
}
292
365
293
366
impl < T > fmt:: Debug for Pointers < T > {
294
367
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
368
+ let prev = self . get_prev ( ) ;
369
+ let next = self . get_next ( ) ;
295
370
f. debug_struct ( "Pointers" )
296
- . field ( "prev" , & self . prev )
297
- . field ( "next" , & self . next )
371
+ . field ( "prev" , & prev)
372
+ . field ( "next" , & next)
298
373
. finish ( )
299
374
}
300
375
}
@@ -321,7 +396,7 @@ mod tests {
321
396
}
322
397
323
398
unsafe fn from_raw ( ptr : NonNull < Entry > ) -> Pin < & ' a Entry > {
324
- Pin :: new ( & * ptr. as_ptr ( ) )
399
+ Pin :: new_unchecked ( & * ptr. as_ptr ( ) )
325
400
}
326
401
327
402
unsafe fn pointers ( mut target : NonNull < Entry > ) -> NonNull < Pointers < Entry > > {
@@ -361,8 +436,8 @@ mod tests {
361
436
362
437
macro_rules! assert_clean {
363
438
( $e: ident) => { {
364
- assert!( $e. pointers. next . is_none( ) ) ;
365
- assert!( $e. pointers. prev . is_none( ) ) ;
439
+ assert!( $e. pointers. get_next ( ) . is_none( ) ) ;
440
+ assert!( $e. pointers. get_prev ( ) . is_none( ) ) ;
366
441
} } ;
367
442
}
368
443
@@ -460,8 +535,8 @@ mod tests {
460
535
assert_clean ! ( a) ;
461
536
462
537
assert_ptr_eq ! ( b, list. head) ;
463
- assert_ptr_eq ! ( c, b. pointers. next ) ;
464
- assert_ptr_eq ! ( b, c. pointers. prev ) ;
538
+ assert_ptr_eq ! ( c, b. pointers. get_next ( ) ) ;
539
+ assert_ptr_eq ! ( b, c. pointers. get_prev ( ) ) ;
465
540
466
541
let items = collect_list ( & mut list) ;
467
542
assert_eq ! ( [ 31 , 7 ] . to_vec( ) , items) ;
@@ -476,8 +551,8 @@ mod tests {
476
551
assert ! ( list. remove( ptr( & b) ) . is_some( ) ) ;
477
552
assert_clean ! ( b) ;
478
553
479
- assert_ptr_eq ! ( c, a. pointers. next ) ;
480
- assert_ptr_eq ! ( a, c. pointers. prev ) ;
554
+ assert_ptr_eq ! ( c, a. pointers. get_next ( ) ) ;
555
+ assert_ptr_eq ! ( a, c. pointers. get_prev ( ) ) ;
481
556
482
557
let items = collect_list ( & mut list) ;
483
558
assert_eq ! ( [ 31 , 5 ] . to_vec( ) , items) ;
@@ -493,7 +568,7 @@ mod tests {
493
568
assert ! ( list. remove( ptr( & c) ) . is_some( ) ) ;
494
569
assert_clean ! ( c) ;
495
570
496
- assert ! ( b. pointers. next . is_none( ) ) ;
571
+ assert ! ( b. pointers. get_next ( ) . is_none( ) ) ;
497
572
assert_ptr_eq ! ( b, list. tail) ;
498
573
499
574
let items = collect_list ( & mut list) ;
@@ -516,8 +591,8 @@ mod tests {
516
591
assert_ptr_eq ! ( b, list. head) ;
517
592
assert_ptr_eq ! ( b, list. tail) ;
518
593
519
- assert ! ( b. pointers. next . is_none( ) ) ;
520
- assert ! ( b. pointers. prev . is_none( ) ) ;
594
+ assert ! ( b. pointers. get_next ( ) . is_none( ) ) ;
595
+ assert ! ( b. pointers. get_prev ( ) . is_none( ) ) ;
521
596
522
597
let items = collect_list ( & mut list) ;
523
598
assert_eq ! ( [ 7 ] . to_vec( ) , items) ;
@@ -536,8 +611,8 @@ mod tests {
536
611
assert_ptr_eq ! ( a, list. head) ;
537
612
assert_ptr_eq ! ( a, list. tail) ;
538
613
539
- assert ! ( a. pointers. next . is_none( ) ) ;
540
- assert ! ( a. pointers. prev . is_none( ) ) ;
614
+ assert ! ( a. pointers. get_next ( ) . is_none( ) ) ;
615
+ assert ! ( a. pointers. get_prev ( ) . is_none( ) ) ;
541
616
542
617
let items = collect_list ( & mut list) ;
543
618
assert_eq ! ( [ 5 ] . to_vec( ) , items) ;
0 commit comments