@@ -245,8 +245,20 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
245245 self . first . is_null ( )
246246 }
247247
248- /// Add the provided item to the back of the list.
249- pub fn push_back ( & mut self , item : ListArc < T , ID > ) {
248+ /// Inserts `item` before `next` in the cycle.
249+ ///
250+ /// Returns a pointer to the newly inserted element. Never changes `self.first` unless the list
251+ /// is empty.
252+ ///
253+ /// # Safety
254+ ///
255+ /// * `next` must be an element in this list or null.
256+ /// * if `next` is null, then the list must be empty.
257+ unsafe fn insert_inner (
258+ & mut self ,
259+ item : ListArc < T , ID > ,
260+ next : * mut ListLinksFields ,
261+ ) -> * mut ListLinksFields {
250262 let raw_item = ListArc :: into_raw ( item) ;
251263 // SAFETY:
252264 // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
@@ -259,16 +271,16 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
259271 // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
260272 let item = unsafe { ListLinks :: fields ( list_links) } ;
261273
262- if self . first . is_null ( ) {
263- self . first = item ;
274+ // Check if the list is empty.
275+ if next . is_null ( ) {
264276 // SAFETY: The caller just gave us ownership of these fields.
265277 // INVARIANT: A linked list with one item should be cyclic.
266278 unsafe {
267279 ( * item) . next = item;
268280 ( * item) . prev = item;
269281 }
282+ self . first = item;
270283 } else {
271- let next = self . first ;
272284 // SAFETY: By the type invariant, this pointer is valid or null. We just checked that
273285 // it's not null, so it must be valid.
274286 let prev = unsafe { ( * next) . prev } ;
@@ -282,45 +294,27 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
282294 ( * next) . prev = item;
283295 }
284296 }
297+
298+ item
299+ }
300+
301+ /// Add the provided item to the back of the list.
302+ pub fn push_back ( & mut self , item : ListArc < T , ID > ) {
303+ // SAFETY:
304+ // * `self.first` is null or in the list.
305+ // * `self.first` is only null if the list is empty.
306+ unsafe { self . insert_inner ( item, self . first ) } ;
285307 }
286308
287309 /// Add the provided item to the front of the list.
288310 pub fn push_front ( & mut self , item : ListArc < T , ID > ) {
289- let raw_item = ListArc :: into_raw ( item) ;
290311 // SAFETY:
291- // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
292- // * If this requirement is violated, then the previous caller of `prepare_to_insert`
293- // violated the safety requirement that they can't give up ownership of the `ListArc`
294- // until they call `post_remove`.
295- // * We own the `ListArc`.
296- // * Removing items] from this list is always done using `remove_internal_inner`, which
297- // calls `post_remove` before giving up ownership.
298- let list_links = unsafe { T :: prepare_to_insert ( raw_item) } ;
299- // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
300- let item = unsafe { ListLinks :: fields ( list_links) } ;
312+ // * `self.first` is null or in the list.
313+ // * `self.first` is only null if the list is empty.
314+ let new_elem = unsafe { self . insert_inner ( item, self . first ) } ;
301315
302- if self . first . is_null ( ) {
303- // SAFETY: The caller just gave us ownership of these fields.
304- // INVARIANT: A linked list with one item should be cyclic.
305- unsafe {
306- ( * item) . next = item;
307- ( * item) . prev = item;
308- }
309- } else {
310- let next = self . first ;
311- // SAFETY: We just checked that `next` is non-null.
312- let prev = unsafe { ( * next) . prev } ;
313- // SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
314- // ownership of the fields on `item`.
315- // INVARIANT: This correctly inserts `item` between `prev` and `next`.
316- unsafe {
317- ( * item) . next = next;
318- ( * item) . prev = prev;
319- ( * prev) . next = item;
320- ( * next) . prev = item;
321- }
322- }
323- self . first = item;
316+ // INVARIANT: `new_elem` is in the list because we just inserted it.
317+ self . first = new_elem;
324318 }
325319
326320 /// Removes the last item from this list.
0 commit comments