@@ -288,10 +288,12 @@ impl<T> [T] {
288288 /// Returns a reference to an element or subslice, without doing bounds
289289 /// checking.
290290 ///
291- /// This is generally not recommended, use with caution!
291+ /// For a safe alternative see [`get`].
292+ ///
293+ /// # Safety
294+ ///
292295 /// Calling this method with an out-of-bounds index is *[undefined behavior]*
293296 /// even if the resulting reference is not used.
294- /// For a safe alternative see [`get`].
295297 ///
296298 /// [`get`]: #method.get
297299 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
@@ -320,10 +322,12 @@ impl<T> [T] {
320322 /// Returns a mutable reference to an element or subslice, without doing
321323 /// bounds checking.
322324 ///
323- /// This is generally not recommended, use with caution!
325+ /// For a safe alternative see [`get_mut`].
326+ ///
327+ /// # Safety
328+ ///
324329 /// Calling this method with an out-of-bounds index is *[undefined behavior]*
325330 /// even if the resulting reference is not used.
326- /// For a safe alternative see [`get_mut`].
327331 ///
328332 /// [`get_mut`]: #method.get_mut
329333 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
@@ -865,8 +869,9 @@ impl<T> [T] {
865869 pub fn chunks_exact ( & self , chunk_size : usize ) -> ChunksExact < ' _ , T > {
866870 assert_ne ! ( chunk_size, 0 ) ;
867871 let rem = self . len ( ) % chunk_size;
868- let len = self . len ( ) - rem;
869- let ( fst, snd) = self . split_at ( len) ;
872+ let fst_len = self . len ( ) - rem;
873+ // SAFETY: 0 <= fst_len <= self.len() by construction above
874+ let ( fst, snd) = unsafe { self . split_at_unchecked ( fst_len) } ;
870875 ChunksExact { v : fst, rem : snd, chunk_size }
871876 }
872877
@@ -910,8 +915,9 @@ impl<T> [T] {
910915 pub fn chunks_exact_mut ( & mut self , chunk_size : usize ) -> ChunksExactMut < ' _ , T > {
911916 assert_ne ! ( chunk_size, 0 ) ;
912917 let rem = self . len ( ) % chunk_size;
913- let len = self . len ( ) - rem;
914- let ( fst, snd) = self . split_at_mut ( len) ;
918+ let fst_len = self . len ( ) - rem;
919+ // SAFETY: 0 <= fst_len <= self.len() by construction above
920+ let ( fst, snd) = unsafe { self . split_at_mut_unchecked ( fst_len) } ;
915921 ChunksExactMut { v : fst, rem : snd, chunk_size }
916922 }
917923
@@ -1063,7 +1069,8 @@ impl<T> [T] {
10631069 pub fn rchunks_exact ( & self , chunk_size : usize ) -> RChunksExact < ' _ , T > {
10641070 assert ! ( chunk_size != 0 ) ;
10651071 let rem = self . len ( ) % chunk_size;
1066- let ( fst, snd) = self . split_at ( rem) ;
1072+ // SAFETY: 0 <= rem <= self.len() by construction above
1073+ let ( fst, snd) = unsafe { self . split_at_unchecked ( rem) } ;
10671074 RChunksExact { v : snd, rem : fst, chunk_size }
10681075 }
10691076
@@ -1108,7 +1115,8 @@ impl<T> [T] {
11081115 pub fn rchunks_exact_mut ( & mut self , chunk_size : usize ) -> RChunksExactMut < ' _ , T > {
11091116 assert ! ( chunk_size != 0 ) ;
11101117 let rem = self . len ( ) % chunk_size;
1111- let ( fst, snd) = self . split_at_mut ( rem) ;
1118+ // SAFETY: 0 <= rem <= self.len() by construction above
1119+ let ( fst, snd) = unsafe { self . split_at_mut_unchecked ( rem) } ;
11121120 RChunksExactMut { v : snd, rem : fst, chunk_size }
11131121 }
11141122
@@ -1129,26 +1137,29 @@ impl<T> [T] {
11291137 ///
11301138 /// {
11311139 /// let (left, right) = v.split_at(0);
1132- /// assert !(left == []);
1133- /// assert !(right == [1, 2, 3, 4, 5, 6]);
1140+ /// assert_eq !(left, []);
1141+ /// assert_eq !(right, [1, 2, 3, 4, 5, 6]);
11341142 /// }
11351143 ///
11361144 /// {
11371145 /// let (left, right) = v.split_at(2);
1138- /// assert !(left == [1, 2]);
1139- /// assert !(right == [3, 4, 5, 6]);
1146+ /// assert_eq !(left, [1, 2]);
1147+ /// assert_eq !(right, [3, 4, 5, 6]);
11401148 /// }
11411149 ///
11421150 /// {
11431151 /// let (left, right) = v.split_at(6);
1144- /// assert !(left == [1, 2, 3, 4, 5, 6]);
1145- /// assert !(right == []);
1152+ /// assert_eq !(left, [1, 2, 3, 4, 5, 6]);
1153+ /// assert_eq !(right, []);
11461154 /// }
11471155 /// ```
11481156 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
11491157 #[ inline]
11501158 pub fn split_at ( & self , mid : usize ) -> ( & [ T ] , & [ T ] ) {
1151- ( & self [ ..mid] , & self [ mid..] )
1159+ assert ! ( mid <= self . len( ) ) ;
1160+ // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
1161+ // fulfills the requirements of `from_raw_parts_mut`.
1162+ unsafe { self . split_at_unchecked ( mid) }
11521163 }
11531164
11541165 /// Divides one mutable slice into two at an index.
@@ -1168,26 +1179,115 @@ impl<T> [T] {
11681179 /// // scoped to restrict the lifetime of the borrows
11691180 /// {
11701181 /// let (left, right) = v.split_at_mut(2);
1171- /// assert !(left == [1, 0]);
1172- /// assert !(right == [3, 0, 5, 6]);
1182+ /// assert_eq !(left, [1, 0]);
1183+ /// assert_eq !(right, [3, 0, 5, 6]);
11731184 /// left[1] = 2;
11741185 /// right[1] = 4;
11751186 /// }
1176- /// assert !(v == [1, 2, 3, 4, 5, 6]);
1187+ /// assert_eq !(v, [1, 2, 3, 4, 5, 6]);
11771188 /// ```
11781189 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
11791190 #[ inline]
11801191 pub fn split_at_mut ( & mut self , mid : usize ) -> ( & mut [ T ] , & mut [ T ] ) {
1181- let len = self . len ( ) ;
1182- let ptr = self . as_mut_ptr ( ) ;
1183-
1192+ assert ! ( mid <= self . len( ) ) ;
11841193 // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
11851194 // fulfills the requirements of `from_raw_parts_mut`.
1186- unsafe {
1187- assert ! ( mid <= len ) ;
1195+ unsafe { self . split_at_mut_unchecked ( mid ) }
1196+ }
11881197
1189- ( from_raw_parts_mut ( ptr, mid) , from_raw_parts_mut ( ptr. add ( mid) , len - mid) )
1190- }
1198+ /// Divides one slice into two at an index, without doing bounds checking.
1199+ ///
1200+ /// The first will contain all indices from `[0, mid)` (excluding
1201+ /// the index `mid` itself) and the second will contain all
1202+ /// indices from `[mid, len)` (excluding the index `len` itself).
1203+ ///
1204+ /// For a safe alternative see [`split_at`].
1205+ ///
1206+ /// # Safety
1207+ ///
1208+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
1209+ /// even if the resulting reference is not used. The caller has to ensure that
1210+ /// `0 <= mid <= self.len()`.
1211+ ///
1212+ /// [`split_at`]: #method.split_at
1213+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1214+ ///
1215+ /// # Examples
1216+ ///
1217+ /// ```compile_fail
1218+ /// #![feature(slice_split_at_unchecked)]
1219+ ///
1220+ /// let v = [1, 2, 3, 4, 5, 6];
1221+ ///
1222+ /// unsafe {
1223+ /// let (left, right) = v.split_at_unchecked(0);
1224+ /// assert_eq!(left, []);
1225+ /// assert_eq!(right, [1, 2, 3, 4, 5, 6]);
1226+ /// }
1227+ ///
1228+ /// unsafe {
1229+ /// let (left, right) = v.split_at_unchecked(2);
1230+ /// assert_eq!(left, [1, 2]);
1231+ /// assert_eq!(right, [3, 4, 5, 6]);
1232+ /// }
1233+ ///
1234+ /// unsafe {
1235+ /// let (left, right) = v.split_at_unchecked(6);
1236+ /// assert_eq!(left, [1, 2, 3, 4, 5, 6]);
1237+ /// assert_eq!(right, []);
1238+ /// }
1239+ /// ```
1240+ #[ unstable( feature = "slice_split_at_unchecked" , reason = "new API" , issue = "76014" ) ]
1241+ #[ inline]
1242+ unsafe fn split_at_unchecked ( & self , mid : usize ) -> ( & [ T ] , & [ T ] ) {
1243+ // SAFETY: Caller has to check that `0 <= mid <= self.len()`
1244+ unsafe { ( self . get_unchecked ( ..mid) , self . get_unchecked ( mid..) ) }
1245+ }
1246+
1247+ /// Divides one mutable slice into two at an index, without doing bounds checking.
1248+ ///
1249+ /// The first will contain all indices from `[0, mid)` (excluding
1250+ /// the index `mid` itself) and the second will contain all
1251+ /// indices from `[mid, len)` (excluding the index `len` itself).
1252+ ///
1253+ /// For a safe alternative see [`split_at_mut`].
1254+ ///
1255+ /// # Safety
1256+ ///
1257+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
1258+ /// even if the resulting reference is not used. The caller has to ensure that
1259+ /// `0 <= mid <= self.len()`.
1260+ ///
1261+ /// [`split_at_mut`]: #method.split_at_mut
1262+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1263+ ///
1264+ /// # Examples
1265+ ///
1266+ /// ```compile_fail
1267+ /// #![feature(slice_split_at_unchecked)]
1268+ ///
1269+ /// let mut v = [1, 0, 3, 0, 5, 6];
1270+ /// // scoped to restrict the lifetime of the borrows
1271+ /// unsafe {
1272+ /// let (left, right) = v.split_at_mut_unchecked(2);
1273+ /// assert_eq!(left, [1, 0]);
1274+ /// assert_eq!(right, [3, 0, 5, 6]);
1275+ /// left[1] = 2;
1276+ /// right[1] = 4;
1277+ /// }
1278+ /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
1279+ /// ```
1280+ #[ unstable( feature = "slice_split_at_unchecked" , reason = "new API" , issue = "76014" ) ]
1281+ #[ inline]
1282+ unsafe fn split_at_mut_unchecked ( & mut self , mid : usize ) -> ( & mut [ T ] , & mut [ T ] ) {
1283+ let len = self . len ( ) ;
1284+ let ptr = self . as_mut_ptr ( ) ;
1285+
1286+ // SAFETY: Caller has to check that `0 <= mid <= self.len()`.
1287+ //
1288+ // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
1289+ // is fine.
1290+ unsafe { ( from_raw_parts_mut ( ptr, mid) , from_raw_parts_mut ( ptr. add ( mid) , len - mid) ) }
11911291 }
11921292
11931293 /// Returns an iterator over subslices separated by elements that match
0 commit comments