@@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
944
944
return ;
945
945
}
946
946
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.
952
962
//
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`.
954
978
//
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) ;
999
988
}
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;
1005
1008
}
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( ) ) ;
1006
1013
}
1007
1014
1008
1015
/// Shortens the deque, keeping the first `len` elements and dropping
0 commit comments