@@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
944944 return ;
945945 }
946946
947- if target_cap < self . capacity ( ) {
948- // There are three cases of interest:
949- // All elements are out of desired bounds
950- // Elements are contiguous, and head is out of desired bounds
951- // Elements are discontiguous, and tail is out of desired bounds
947+ // There are three cases of interest:
948+ // All elements are out of desired bounds
949+ // Elements are contiguous, and tail is out of desired bounds
950+ // Elements are discontiguous
951+ //
952+ // At all other times, element positions are unaffected.
953+
954+ // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
955+ // overflow.
956+ let tail_outside = ( target_cap + 1 ..=self . capacity ( ) ) . contains ( & ( self . head + self . len ) ) ;
957+
958+ if self . len == 0 {
959+ self . head = 0 ;
960+ } else if self . head >= target_cap && tail_outside {
961+ // Head and tail are both out of bounds, so copy all of them to the front.
952962 //
953- // At all other times, element positions are unaffected.
963+ // H := head
964+ // L := last element
965+ // H L
966+ // [. . . . . . . . o o o o o o o . ]
967+ // H L
968+ // [o o o o o o o . ]
969+ unsafe {
970+ // nonoverlapping because `self.head >= target_cap >= self.len`.
971+ self . copy_nonoverlapping ( self . head , 0 , self . len ) ;
972+ }
973+ self . head = 0 ;
974+ } else if self . head < target_cap && tail_outside {
975+ // Head is in bounds, tail is out of bounds.
976+ // Copy the overflowing part to the beginning of the
977+ // buffer. This won't overlap because `target_cap >= self.len`.
954978 //
955- // Indicates that elements at the head should be moved.
956-
957- let tail_outside = ( target_cap + 1 ..=self . capacity ( ) ) . contains ( & ( self . head + self . len ) ) ;
958- // Move elements from out of desired bounds (positions after target_cap)
959- if self . len == 0 {
960- self . head = 0 ;
961- } else if self . head >= target_cap && tail_outside {
962- // H := head
963- // L := last element
964- // H L
965- // [. . . . . . . . o o o o o o o . ]
966- // H L
967- // [o o o o o o o . ]
968- unsafe {
969- // nonoverlapping because self.head >= target_cap >= self.len
970- self . copy_nonoverlapping ( self . head , 0 , self . len ) ;
971- }
972- self . head = 0 ;
973- } else if self . head < target_cap && tail_outside {
974- // H := head
975- // L := last element
976- // H L
977- // [. . . o o o o o o o . . . . . . ]
978- // L H
979- // [o o . o o o o o ]
980- let len = self . head + self . len - target_cap;
981- unsafe {
982- self . copy_nonoverlapping ( target_cap, 0 , len) ;
983- }
984- } else if self . head >= target_cap {
985- // H := head
986- // L := last element
987- // L H
988- // [o o o o o . . . . . . . . . o o ]
989- // L H
990- // [o o o o o . o o ]
991- let len = self . capacity ( ) - self . head ;
992- let new_head = target_cap - len;
993- unsafe {
994- // can't use copy_nonoverlapping here for the same reason
995- // as in `handle_capacity_increase()`
996- self . copy ( self . head , new_head, len) ;
997- }
998- self . head = new_head;
979+ // H := head
980+ // L := last element
981+ // H L
982+ // [. . . o o o o o o o . . . . . . ]
983+ // L H
984+ // [o o . o o o o o ]
985+ let len = self . head + self . len - target_cap;
986+ unsafe {
987+ self . copy_nonoverlapping ( target_cap, 0 , len) ;
999988 }
1000-
1001- self . buf . shrink_to_fit ( target_cap) ;
1002-
1003- debug_assert ! ( self . head < self . capacity( ) || self . capacity( ) == 0 ) ;
1004- debug_assert ! ( self . len <= self . capacity( ) ) ;
989+ } else if !self . is_contiguous ( ) {
990+ // The head slice is at least partially out of bounds, tail is in bounds.
991+ // Copy the head backwards so it lines up with the target capacity.
992+ // This won't overlap because `target_cap >= self.len`.
993+ //
994+ // H := head
995+ // L := last element
996+ // L H
997+ // [o o o o o . . . . . . . . . o o ]
998+ // L H
999+ // [o o o o o . o o ]
1000+ let head_len = self . capacity ( ) - self . head ;
1001+ let new_head = target_cap - head_len;
1002+ unsafe {
1003+ // can't use `copy_nonoverlapping()` here because the new and old
1004+ // regions for the head might overlap.
1005+ self . copy ( self . head , new_head, head_len) ;
1006+ }
1007+ self . head = new_head;
10051008 }
1009+ self . buf . shrink_to_fit ( target_cap) ;
1010+
1011+ debug_assert ! ( self . head < self . capacity( ) || self . capacity( ) == 0 ) ;
1012+ debug_assert ! ( self . len <= self . capacity( ) ) ;
10061013 }
10071014
10081015 /// Shortens the deque, keeping the first `len` elements and dropping
0 commit comments