@@ -86,6 +86,9 @@ impl<T> Clone for Iter<'_, T> {
86
86
/// [`LinkedList`]: struct.LinkedList.html
87
87
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
88
88
pub struct IterMut < ' a , T : ' a > {
89
+ // We do *not* exclusively own the entire list here, references to node's `element`
90
+ // have been handed out by the iterator! So be careful when using this; the methods
91
+ // called must be aware that there can be aliasing pointers to `element`.
89
92
list : & ' a mut LinkedList < T > ,
90
93
head : Option < NonNull < Node < T > > > ,
91
94
tail : Option < NonNull < Node < T > > > ,
@@ -143,14 +146,17 @@ impl<T> LinkedList<T> {
143
146
/// Adds the given node to the front of the list.
144
147
#[ inline]
145
148
fn push_front_node ( & mut self , mut node : Box < Node < T > > ) {
149
+ // This method takes care not to create mutable references to whole nodes,
150
+ // to maintain validity of aliasing pointers into `element`.
146
151
unsafe {
147
152
node. next = self . head ;
148
153
node. prev = None ;
149
154
let node = Some ( Box :: into_raw_non_null ( node) ) ;
150
155
151
156
match self . head {
152
157
None => self . tail = node,
153
- Some ( mut head) => head. as_mut ( ) . prev = node,
158
+ // Not creating new mutable (unique!) references overlapping `element`.
159
+ Some ( head) => ( * head. as_ptr ( ) ) . prev = node,
154
160
}
155
161
156
162
self . head = node;
@@ -161,13 +167,16 @@ impl<T> LinkedList<T> {
161
167
/// Removes and returns the node at the front of the list.
162
168
#[ inline]
163
169
fn pop_front_node ( & mut self ) -> Option < Box < Node < T > > > {
170
+ // This method takes care not to create mutable references to whole nodes,
171
+ // to maintain validity of aliasing pointers into `element`.
164
172
self . head . map ( |node| unsafe {
165
173
let node = Box :: from_raw ( node. as_ptr ( ) ) ;
166
174
self . head = node. next ;
167
175
168
176
match self . head {
169
177
None => self . tail = None ,
170
- Some ( mut head) => head. as_mut ( ) . prev = None ,
178
+ // Not creating new mutable (unique!) references overlapping `element`.
179
+ Some ( head) => ( * head. as_ptr ( ) ) . prev = None ,
171
180
}
172
181
173
182
self . len -= 1 ;
@@ -178,14 +187,17 @@ impl<T> LinkedList<T> {
178
187
/// Adds the given node to the back of the list.
179
188
#[ inline]
180
189
fn push_back_node ( & mut self , mut node : Box < Node < T > > ) {
190
+ // This method takes care not to create mutable references to whole nodes,
191
+ // to maintain validity of aliasing pointers into `element`.
181
192
unsafe {
182
193
node. next = None ;
183
194
node. prev = self . tail ;
184
195
let node = Some ( Box :: into_raw_non_null ( node) ) ;
185
196
186
197
match self . tail {
187
198
None => self . head = node,
188
- Some ( mut tail) => tail. as_mut ( ) . next = node,
199
+ // Not creating new mutable (unique!) references overlapping `element`.
200
+ Some ( tail) => ( * tail. as_ptr ( ) ) . next = node,
189
201
}
190
202
191
203
self . tail = node;
@@ -196,13 +208,16 @@ impl<T> LinkedList<T> {
196
208
/// Removes and returns the node at the back of the list.
197
209
#[ inline]
198
210
fn pop_back_node ( & mut self ) -> Option < Box < Node < T > > > {
211
+ // This method takes care not to create mutable references to whole nodes,
212
+ // to maintain validity of aliasing pointers into `element`.
199
213
self . tail . map ( |node| unsafe {
200
214
let node = Box :: from_raw ( node. as_ptr ( ) ) ;
201
215
self . tail = node. prev ;
202
216
203
217
match self . tail {
204
218
None => self . head = None ,
205
- Some ( mut tail) => tail. as_mut ( ) . next = None ,
219
+ // Not creating new mutable (unique!) references overlapping `element`.
220
+ Some ( tail) => ( * tail. as_ptr ( ) ) . next = None ,
206
221
}
207
222
208
223
self . len -= 1 ;
@@ -213,18 +228,22 @@ impl<T> LinkedList<T> {
213
228
/// Unlinks the specified node from the current list.
214
229
///
215
230
/// Warning: this will not check that the provided node belongs to the current list.
231
+ ///
232
+ /// This method takes care not to create mutable references to `element`, to
233
+ /// maintain validity of aliasing pointers.
216
234
#[ inline]
217
235
unsafe fn unlink_node ( & mut self , mut node : NonNull < Node < T > > ) {
218
- let node = node. as_mut ( ) ;
236
+ let node = node. as_mut ( ) ; // this one is ours now, we can create an &mut.
219
237
238
+ // Not creating new mutable (unique!) references overlapping `element`.
220
239
match node. prev {
221
- Some ( mut prev) => prev. as_mut ( ) . next = node. next . clone ( ) ,
240
+ Some ( prev) => ( * prev. as_ptr ( ) ) . next = node. next . clone ( ) ,
222
241
// this node is the head node
223
242
None => self . head = node. next . clone ( ) ,
224
243
} ;
225
244
226
245
match node. next {
227
- Some ( mut next) => next. as_mut ( ) . prev = node. prev . clone ( ) ,
246
+ Some ( next) => ( * next. as_ptr ( ) ) . prev = node. prev . clone ( ) ,
228
247
// this node is the tail node
229
248
None => self . tail = node. prev . clone ( ) ,
230
249
} ;
@@ -297,6 +316,8 @@ impl<T> LinkedList<T> {
297
316
match self . tail {
298
317
None => mem:: swap ( self , other) ,
299
318
Some ( mut tail) => {
319
+ // `as_mut` is okay here because we have exclusive access to the entirety
320
+ // of both lists.
300
321
if let Some ( mut other_head) = other. head . take ( ) {
301
322
unsafe {
302
323
tail. as_mut ( ) . next = Some ( other_head) ;
@@ -916,9 +937,11 @@ impl<T> IterMut<'_, T> {
916
937
issue = "27794" ) ]
917
938
pub fn insert_next ( & mut self , element : T ) {
918
939
match self . head {
940
+ // `push_back` is okay with aliasing `element` references
919
941
None => self . list . push_back ( element) ,
920
- Some ( mut head) => unsafe {
921
- let mut prev = match head. as_ref ( ) . prev {
942
+ Some ( head) => unsafe {
943
+ let prev = match head. as_ref ( ) . prev {
944
+ // `push_front` is okay with aliasing nodes
922
945
None => return self . list . push_front ( element) ,
923
946
Some ( prev) => prev,
924
947
} ;
@@ -929,8 +952,10 @@ impl<T> IterMut<'_, T> {
929
952
element,
930
953
} ) ) ;
931
954
932
- prev. as_mut ( ) . next = node;
933
- head. as_mut ( ) . prev = node;
955
+ // Not creating references to entire nodes to not invalidate the
956
+ // reference to `element` we handed to the user.
957
+ ( * prev. as_ptr ( ) ) . next = node;
958
+ ( * head. as_ptr ( ) ) . prev = node;
934
959
935
960
self . list . len += 1 ;
936
961
} ,
@@ -994,6 +1019,7 @@ impl<T, F> Iterator for DrainFilter<'_, T, F>
994
1019
self . idx += 1 ;
995
1020
996
1021
if ( self . pred ) ( & mut node. as_mut ( ) . element ) {
1022
+ // `unlink_node` is okay with aliasing `element` references.
997
1023
self . list . unlink_node ( node) ;
998
1024
return Some ( Box :: from_raw ( node. as_ptr ( ) ) . element ) ;
999
1025
}
0 commit comments