Skip to content

Commit 8510cf6

Browse files
committed
Update slice::split_array_*() methods to never panic
Splitting a slice returns an Option, akin to get().
1 parent a11235d commit 8510cf6

File tree

3 files changed

+68
-54
lines changed

3 files changed

+68
-54
lines changed

library/core/src/array/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ impl<T, const N: usize> [T; N] {
667667
)]
668668
#[inline]
669669
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
670-
(&self[..]).split_array_ref::<M>()
670+
(&self[..]).split_array_ref::<M>().unwrap()
671671
}
672672

673673
/// Divides one mutable array reference into two at an index.
@@ -700,7 +700,7 @@ impl<T, const N: usize> [T; N] {
700700
)]
701701
#[inline]
702702
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
703-
(&mut self[..]).split_array_mut::<M>()
703+
(&mut self[..]).split_array_mut::<M>().unwrap()
704704
}
705705

706706
/// Divides one array reference into two at an index from the end.
@@ -745,7 +745,7 @@ impl<T, const N: usize> [T; N] {
745745
)]
746746
#[inline]
747747
pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
748-
(&self[..]).rsplit_array_ref::<M>()
748+
(&self[..]).rsplit_array_ref::<M>().unwrap()
749749
}
750750

751751
/// Divides one mutable array reference into two at an index from the end.
@@ -778,7 +778,7 @@ impl<T, const N: usize> [T; N] {
778778
)]
779779
#[inline]
780780
pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
781-
(&mut self[..]).rsplit_array_mut::<M>()
781+
(&mut self[..]).rsplit_array_mut::<M>().unwrap()
782782
}
783783
}
784784

library/core/src/slice/mod.rs

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,9 +1764,7 @@ impl<T> [T] {
17641764
/// the index `N` itself) and the slice will contain all
17651765
/// indices from `[N, len)` (excluding the index `len` itself).
17661766
///
1767-
/// # Panics
1768-
///
1769-
/// Panics if `N > len`.
1767+
/// Returns `None` if the slice has less than `N` elements.
17701768
///
17711769
/// # Examples
17721770
///
@@ -1776,31 +1774,38 @@ impl<T> [T] {
17761774
/// let v = &[1, 2, 3, 4, 5, 6][..];
17771775
///
17781776
/// {
1779-
/// let (left, right) = v.split_array_ref::<0>();
1777+
/// let (left, right) = v.split_array_ref::<0>().unwrap();
17801778
/// assert_eq!(left, &[]);
17811779
/// assert_eq!(right, [1, 2, 3, 4, 5, 6]);
17821780
/// }
17831781
///
17841782
/// {
1785-
/// let (left, right) = v.split_array_ref::<2>();
1783+
/// let (left, right) = v.split_array_ref::<2>().unwrap();
17861784
/// assert_eq!(left, &[1, 2]);
17871785
/// assert_eq!(right, [3, 4, 5, 6]);
17881786
/// }
17891787
///
17901788
/// {
1791-
/// let (left, right) = v.split_array_ref::<6>();
1789+
/// let (left, right) = v.split_array_ref::<6>().unwrap();
17921790
/// assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
17931791
/// assert_eq!(right, []);
17941792
/// }
1793+
///
1794+
/// assert!(v.split_array_ref::<7>().is_none());
17951795
/// ```
17961796
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
17971797
#[inline]
17981798
#[track_caller]
17991799
#[must_use]
1800-
pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) {
1801-
let (a, b) = self.split_at(N);
1802-
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
1803-
unsafe { (&*(a.as_ptr() as *const [T; N]), b) }
1800+
pub fn split_array_ref<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
1801+
if N > self.len() {
1802+
None
1803+
} else {
1804+
// SAFETY: 0 <= N <= len
1805+
let (a, b) = unsafe { self.split_at_unchecked(N) };
1806+
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
1807+
Some(unsafe { (&*(a.as_ptr() as *const [T; N]), b) })
1808+
}
18041809
}
18051810

18061811
/// Divides one mutable slice into an array and a remainder slice at an index.
@@ -1809,31 +1814,36 @@ impl<T> [T] {
18091814
/// the index `N` itself) and the slice will contain all
18101815
/// indices from `[N, len)` (excluding the index `len` itself).
18111816
///
1812-
/// # Panics
1813-
///
1814-
/// Panics if `N > len`.
1817+
/// Returns `None` if the slice has less than `N` elements.
18151818
///
18161819
/// # Examples
18171820
///
18181821
/// ```
18191822
/// #![feature(split_array)]
18201823
///
18211824
/// let mut v = &mut [1, 0, 3, 0, 5, 6][..];
1822-
/// let (left, right) = v.split_array_mut::<2>();
1825+
/// let (left, right) = v.split_array_mut::<2>().unwrap();
18231826
/// assert_eq!(left, &mut [1, 0]);
18241827
/// assert_eq!(right, [3, 0, 5, 6]);
18251828
/// left[1] = 2;
18261829
/// right[1] = 4;
18271830
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
1831+
///
1832+
/// assert!(v.split_array_mut::<7>().is_none());
18281833
/// ```
18291834
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
18301835
#[inline]
18311836
#[track_caller]
18321837
#[must_use]
1833-
pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) {
1834-
let (a, b) = self.split_at_mut(N);
1835-
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
1836-
unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) }
1838+
pub fn split_array_mut<const N: usize>(&mut self) -> Option<(&mut [T; N], &mut [T])> {
1839+
if N > self.len() {
1840+
None
1841+
} else {
1842+
// SAFETY: 0 <= N <= len
1843+
let (a, b) = unsafe { self.split_at_mut_unchecked(N) };
1844+
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
1845+
Some(unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) })
1846+
}
18371847
}
18381848

18391849
/// Divides one slice into an array and a remainder slice at an index from
@@ -1843,9 +1853,7 @@ impl<T> [T] {
18431853
/// the index `len - N` itself) and the array will contain all
18441854
/// indices from `[len - N, len)` (excluding the index `len` itself).
18451855
///
1846-
/// # Panics
1847-
///
1848-
/// Panics if `N > len`.
1856+
/// Returns `None` if the slice has less than `N` elements.
18491857
///
18501858
/// # Examples
18511859
///
@@ -1855,31 +1863,37 @@ impl<T> [T] {
18551863
/// let v = &[1, 2, 3, 4, 5, 6][..];
18561864
///
18571865
/// {
1858-
/// let (left, right) = v.rsplit_array_ref::<0>();
1866+
/// let (left, right) = v.rsplit_array_ref::<0>().unwrap();
18591867
/// assert_eq!(left, [1, 2, 3, 4, 5, 6]);
18601868
/// assert_eq!(right, &[]);
18611869
/// }
18621870
///
18631871
/// {
1864-
/// let (left, right) = v.rsplit_array_ref::<2>();
1872+
/// let (left, right) = v.rsplit_array_ref::<2>().unwrap();
18651873
/// assert_eq!(left, [1, 2, 3, 4]);
18661874
/// assert_eq!(right, &[5, 6]);
18671875
/// }
18681876
///
18691877
/// {
1870-
/// let (left, right) = v.rsplit_array_ref::<6>();
1878+
/// let (left, right) = v.rsplit_array_ref::<6>().unwrap();
18711879
/// assert_eq!(left, []);
18721880
/// assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
18731881
/// }
1882+
///
1883+
/// assert!(v.rsplit_array_ref::<7>().is_none());
18741884
/// ```
18751885
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
18761886
#[inline]
18771887
#[must_use]
1878-
pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]) {
1879-
assert!(N <= self.len());
1880-
let (a, b) = self.split_at(self.len() - N);
1881-
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at)
1882-
unsafe { (a, &*(b.as_ptr() as *const [T; N])) }
1888+
pub fn rsplit_array_ref<const N: usize>(&self) -> Option<(&[T], &[T; N])> {
1889+
if N > self.len() {
1890+
None
1891+
} else {
1892+
// SAFETY: N <= len; thus 0 <= len - N <= len
1893+
let (a, b) = unsafe { self.split_at_unchecked(self.len() - N) };
1894+
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at)
1895+
Some(unsafe { (a, &*(b.as_ptr() as *const [T; N])) })
1896+
}
18831897
}
18841898

18851899
/// Divides one mutable slice into an array and a remainder slice at an
@@ -1889,31 +1903,35 @@ impl<T> [T] {
18891903
/// the index `N` itself) and the array will contain all
18901904
/// indices from `[len - N, len)` (excluding the index `len` itself).
18911905
///
1892-
/// # Panics
1893-
///
1894-
/// Panics if `N > len`.
1906+
/// Returns `None` if the slice has less than `N` elements.
18951907
///
18961908
/// # Examples
18971909
///
18981910
/// ```
18991911
/// #![feature(split_array)]
19001912
///
19011913
/// let mut v = &mut [1, 0, 3, 0, 5, 6][..];
1902-
/// let (left, right) = v.rsplit_array_mut::<4>();
1914+
/// let (left, right) = v.rsplit_array_mut::<4>().unwrap();
19031915
/// assert_eq!(left, [1, 0]);
19041916
/// assert_eq!(right, &mut [3, 0, 5, 6]);
19051917
/// left[1] = 2;
19061918
/// right[1] = 4;
19071919
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
1920+
///
1921+
/// assert!(v.rsplit_array_mut::<7>().is_none());
19081922
/// ```
19091923
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
19101924
#[inline]
19111925
#[must_use]
1912-
pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]) {
1913-
assert!(N <= self.len());
1914-
let (a, b) = self.split_at_mut(self.len() - N);
1915-
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
1916-
unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) }
1926+
pub fn rsplit_array_mut<const N: usize>(&mut self) -> Option<(&mut [T], &mut [T; N])> {
1927+
if N > self.len() {
1928+
None
1929+
} else {
1930+
// SAFETY: N <= len; thus 0 <= len - N <= len
1931+
let (a, b) = unsafe { self.split_at_mut_unchecked(self.len() - N) };
1932+
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
1933+
Some(unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) })
1934+
}
19171935
}
19181936

19191937
/// Returns an iterator over subslices separated by elements that match

library/core/tests/slice.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,13 +2375,13 @@ fn slice_split_array_mut() {
23752375
let v = &mut [1, 2, 3, 4, 5, 6][..];
23762376

23772377
{
2378-
let (left, right) = v.split_array_mut::<0>();
2378+
let (left, right) = v.split_array_mut::<0>().unwrap();
23792379
assert_eq!(left, &mut []);
23802380
assert_eq!(right, [1, 2, 3, 4, 5, 6]);
23812381
}
23822382

23832383
{
2384-
let (left, right) = v.split_array_mut::<6>();
2384+
let (left, right) = v.split_array_mut::<6>().unwrap();
23852385
assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
23862386
assert_eq!(right, []);
23872387
}
@@ -2392,13 +2392,13 @@ fn slice_rsplit_array_mut() {
23922392
let v = &mut [1, 2, 3, 4, 5, 6][..];
23932393

23942394
{
2395-
let (left, right) = v.rsplit_array_mut::<0>();
2395+
let (left, right) = v.rsplit_array_mut::<0>().unwrap();
23962396
assert_eq!(left, [1, 2, 3, 4, 5, 6]);
23972397
assert_eq!(right, &mut []);
23982398
}
23992399

24002400
{
2401-
let (left, right) = v.rsplit_array_mut::<6>();
2401+
let (left, right) = v.rsplit_array_mut::<6>().unwrap();
24022402
assert_eq!(left, []);
24032403
assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
24042404
}
@@ -2416,36 +2416,32 @@ fn split_as_slice() {
24162416
assert_eq!(split.as_slice(), &[]);
24172417
}
24182418

2419-
#[should_panic]
24202419
#[test]
24212420
fn slice_split_array_ref_out_of_bounds() {
24222421
let v = &[1, 2, 3, 4, 5, 6][..];
24232422

2424-
let _ = v.split_array_ref::<7>();
2423+
assert!(v.split_array_ref::<7>().is_none());
24252424
}
24262425

2427-
#[should_panic]
24282426
#[test]
24292427
fn slice_split_array_mut_out_of_bounds() {
24302428
let v = &mut [1, 2, 3, 4, 5, 6][..];
24312429

2432-
let _ = v.split_array_mut::<7>();
2430+
assert!(v.split_array_mut::<7>().is_none());
24332431
}
24342432

2435-
#[should_panic]
24362433
#[test]
24372434
fn slice_rsplit_array_ref_out_of_bounds() {
24382435
let v = &[1, 2, 3, 4, 5, 6][..];
24392436

2440-
let _ = v.rsplit_array_ref::<7>();
2437+
assert!(v.rsplit_array_ref::<7>().is_none());
24412438
}
24422439

2443-
#[should_panic]
24442440
#[test]
24452441
fn slice_rsplit_array_mut_out_of_bounds() {
24462442
let v = &mut [1, 2, 3, 4, 5, 6][..];
24472443

2448-
let _ = v.rsplit_array_mut::<7>();
2444+
assert!(v.rsplit_array_mut::<7>().is_none());
24492445
}
24502446

24512447
macro_rules! take_tests {

0 commit comments

Comments
 (0)