@@ -1148,7 +1148,10 @@ impl<T> [T] {
11481148 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
11491149 #[ inline]
11501150 pub fn split_at ( & self , mid : usize ) -> ( & [ T ] , & [ T ] ) {
1151- ( & self [ ..mid] , & self [ mid..] )
1151+ assert ! ( mid <= self . len( ) ) ;
1152+ // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
1153+ // fulfills the requirements of `from_raw_parts_mut`.
1154+ unsafe { self . split_at_unchecked ( mid) }
11521155 }
11531156
11541157 /// Divides one mutable slice into two at an index.
@@ -1178,16 +1181,99 @@ impl<T> [T] {
11781181 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
11791182 #[ inline]
11801183 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-
1184+ assert ! ( mid <= self . len( ) ) ;
11841185 // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
11851186 // fulfills the requirements of `from_raw_parts_mut`.
1186- unsafe {
1187- assert ! ( mid <= len ) ;
1187+ unsafe { self . split_at_mut_unchecked ( mid ) }
1188+ }
11881189
1189- ( from_raw_parts_mut ( ptr, mid) , from_raw_parts_mut ( ptr. add ( mid) , len - mid) )
1190- }
1190+ /// Divides one slice into two at an index, without doing bounds checking.
1191+ ///
1192+ /// The first will contain all indices from `[0, mid)` (excluding
1193+ /// the index `mid` itself) and the second will contain all
1194+ /// indices from `[mid, len)` (excluding the index `len` itself).
1195+ ///
1196+ /// This is generally not recommended, use with caution!
1197+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
1198+ /// even if the resulting reference is not used.
1199+ /// For a safe alternative see [`split_at`].
1200+ ///
1201+ /// [`split_at`]: #method.split_at
1202+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1203+ ///
1204+ /// # Examples
1205+ ///
1206+ /// ```compile_fail
1207+ /// #![feature(slice_split_at_unchecked)]
1208+ ///
1209+ /// let v = [1, 2, 3, 4, 5, 6];
1210+ ///
1211+ /// unsafe {
1212+ /// let (left, right) = v.split_at_unchecked(0);
1213+ /// assert!(left == []);
1214+ /// assert!(right == [1, 2, 3, 4, 5, 6]);
1215+ /// }
1216+ ///
1217+ /// unsafe {
1218+ /// let (left, right) = v.split_at_unchecked(2);
1219+ /// assert!(left == [1, 2]);
1220+ /// assert!(right == [3, 4, 5, 6]);
1221+ /// }
1222+ ///
1223+ /// unsafe {
1224+ /// let (left, right) = v.split_at_unchecked(6);
1225+ /// assert!(left == [1, 2, 3, 4, 5, 6]);
1226+ /// assert!(right == []);
1227+ /// }
1228+ /// ```
1229+ #[ unstable( feature = "slice_split_at_unchecked" , reason = "new API" , issue = "76014" ) ]
1230+ #[ inline]
1231+ unsafe fn split_at_unchecked ( & self , mid : usize ) -> ( & [ T ] , & [ T ] ) {
1232+ // SAFETY: Caller has to check that 0 <= mid < self.len()
1233+ unsafe { ( self . get_unchecked ( ..mid) , self . get_unchecked ( mid..) ) }
1234+ }
1235+
1236+ /// Divides one mutable slice into two at an index, without doing bounds checking.
1237+ ///
1238+ /// The first will contain all indices from `[0, mid)` (excluding
1239+ /// the index `mid` itself) and the second will contain all
1240+ /// indices from `[mid, len)` (excluding the index `len` itself).
1241+ ///
1242+ /// This is generally not recommended, use with caution!
1243+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
1244+ /// even if the resulting reference is not used.
1245+ /// For a safe alternative see [`split_at_mut`].
1246+ ///
1247+ /// [`split_at_mut`]: #method.split_at_mut
1248+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1249+ ///
1250+ /// # Examples
1251+ ///
1252+ /// ```compile_fail
1253+ /// #![feature(slice_split_at_unchecked)]
1254+ ///
1255+ /// let mut v = [1, 0, 3, 0, 5, 6];
1256+ /// // scoped to restrict the lifetime of the borrows
1257+ /// unsafe {
1258+ /// let (left, right) = v.split_at_mut_unchecked(2);
1259+ /// assert!(left == [1, 0]);
1260+ /// assert!(right == [3, 0, 5, 6]);
1261+ /// left[1] = 2;
1262+ /// right[1] = 4;
1263+ /// }
1264+ /// assert!(v == [1, 2, 3, 4, 5, 6]);
1265+ /// ```
1266+ #[ unstable( feature = "slice_split_at_unchecked" , reason = "new API" , issue = "76014" ) ]
1267+ #[ inline]
1268+ unsafe fn split_at_mut_unchecked ( & mut self , mid : usize ) -> ( & mut [ T ] , & mut [ T ] ) {
1269+ let len = self . len ( ) ;
1270+ let ptr = self . as_mut_ptr ( ) ;
1271+
1272+ // SAFETY: Caller has to check that 0 <= mid < self.len().
1273+ //
1274+ // [ptr; mid] and [mid; len] are not overlapping, so returning a mutable reference
1275+ // is fine.
1276+ unsafe { ( from_raw_parts_mut ( ptr, mid) , from_raw_parts_mut ( ptr. add ( mid) , len - mid) ) }
11911277 }
11921278
11931279 /// Returns an iterator over subslices separated by elements that match
0 commit comments