Skip to content

Commit fcec20e

Browse files
committed
Don't panic in VecInner::extend and return a Result
Other methods for extending VecInner already return results instead of panicking. In case of VecInner::extend, avoiding a panic by checking that the actual amount of elements to extend with fits beforehand is not generally possible. So attempt to add the elements from the iterator and restore the original length in case of an error.
1 parent b8fa753 commit fcec20e

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
## [Unreleased]
99
- Added `from_bytes_truncating_at_nul` to `CString`
1010
- Added `CString::{into_bytes, into_bytes_with_nul, into_string}`
11+
- Replace panicking in `VecInner::extend` with returning a `Result`.
1112

1213
## [v0.9.2] 2025-11-12
1314

src/linear_map.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ where
586586
I: IntoIterator<Item = (K, V)>,
587587
{
588588
let mut out = Self::new();
589-
out.buffer.extend(iter);
589+
out.buffer
590+
.extend(iter)
591+
.expect("LinearMap::from_iter overflow");
590592
out
591593
}
592594
}

src/vec/mod.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -621,17 +621,19 @@ impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> VecInner<T, LenT, S> {
621621
}
622622

623623
/// Extends the vec from an iterator.
624-
///
625-
/// # Panic
626-
///
627-
/// Panics if the vec cannot hold all elements of the iterator.
628-
pub fn extend<I>(&mut self, iter: I)
624+
pub fn extend<I>(&mut self, iter: I) -> Result<(), CapacityError>
629625
where
630626
I: IntoIterator<Item = T>,
631627
{
632-
for elem in iter {
633-
self.push(elem).ok().unwrap();
634-
}
628+
// Save current length to restore it later in case of an error.
629+
let len = self.len();
630+
631+
iter.into_iter()
632+
.try_for_each(|elem| self.push(elem))
633+
.map_err(|_| {
634+
unsafe { self.set_len(len) };
635+
CapacityError
636+
})
635637
}
636638

637639
/// Clones and appends all elements in a slice to the `Vec`.
@@ -1404,7 +1406,7 @@ impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Extend<T> for VecInner<T, LenT
14041406
where
14051407
I: IntoIterator<Item = T>,
14061408
{
1407-
self.extend(iter);
1409+
self.extend(iter).expect("VecInner::extend overflow");
14081410
}
14091411
}
14101412

@@ -1416,7 +1418,8 @@ where
14161418
where
14171419
I: IntoIterator<Item = &'a T>,
14181420
{
1419-
self.extend(iter.into_iter().cloned());
1421+
self.extend(iter.into_iter().cloned())
1422+
.expect("Vec::extend overflow");
14201423
}
14211424
}
14221425

@@ -1808,7 +1811,7 @@ mod tests {
18081811

18091812
use static_assertions::assert_not_impl_any;
18101813

1811-
use super::{Vec, VecView};
1814+
use super::{CapacityError, Vec, VecView};
18121815

18131816
// Ensure a `Vec` containing `!Send` values stays `!Send` itself.
18141817
assert_not_impl_any!(Vec<*const (), 4>: Send);
@@ -2119,6 +2122,22 @@ mod tests {
21192122
assert_eq!(v.len(), 0);
21202123
}
21212124

2125+
#[test]
2126+
fn extend_size_limit() {
2127+
let mut v: Vec<u8, 4> = Vec::new();
2128+
assert!(v.extend(core::iter::empty()).is_ok());
2129+
assert!(v.is_empty());
2130+
2131+
assert!(v.extend(core::iter::repeat_n(42, 2)).is_ok());
2132+
assert_eq!(&v, &[42, 42]);
2133+
2134+
matches!(v.extend(core::iter::repeat_n(0, 3)), Err(CapacityError));
2135+
assert_eq!(&v, &[42, 42]);
2136+
2137+
assert!(v.extend(core::iter::repeat_n(0, 2)).is_ok());
2138+
assert_eq!(&v, &[42, 42, 0, 0]);
2139+
}
2140+
21222141
#[test]
21232142
fn resize_size_limit() {
21242143
let mut v: Vec<u8, 4> = Vec::new();

0 commit comments

Comments
 (0)