Skip to content

Commit 9ab3225

Browse files
committed
Auto merge of rust-lang#94148 - matthiaskrgr:rollup-jgea68f, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#92902 (Improve the documentation of drain members) - rust-lang#93658 (Stabilize `#[cfg(panic = "...")]`) - rust-lang#93954 (rustdoc-json: buffer output) - rust-lang#93979 (Add debug assertions to validate NUL terminator in c strings) - rust-lang#93990 (pre rust-lang#89862 cleanup) - rust-lang#94006 (Use a `Field` in `ConstraintCategory::ClosureUpvar`) - rust-lang#94086 (Fix ScalarInt to char conversion) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6ae5ffe + c22c9f7 commit 9ab3225

File tree

9 files changed

+87
-47
lines changed

9 files changed

+87
-47
lines changed

alloc/src/collections/binary_heap.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,12 @@ impl<T: Ord> BinaryHeap<T> {
746746
self.rebuild_tail(start);
747747
}
748748

749-
/// Returns an iterator which retrieves elements in heap order.
750-
/// The retrieved elements are removed from the original heap.
751-
/// The remaining elements will be removed on drop in heap order.
749+
/// Clears the binary heap, returning an iterator over the removed elements
750+
/// in heap order. If the iterator is dropped before being fully consumed,
751+
/// it drops the remaining elements in heap order.
752+
///
753+
/// The returned iterator keeps a mutable borrow on the heap to optimize
754+
/// its implementation.
752755
///
753756
/// Note:
754757
/// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
@@ -1158,9 +1161,12 @@ impl<T> BinaryHeap<T> {
11581161
self.len() == 0
11591162
}
11601163

1161-
/// Clears the binary heap, returning an iterator over the removed elements.
1164+
/// Clears the binary heap, returning an iterator over the removed elements
1165+
/// in arbitrary order. If the iterator is dropped before being fully
1166+
/// consumed, it drops the remaining elements in arbitrary order.
11621167
///
1163-
/// The elements are removed in arbitrary order.
1168+
/// The returned iterator keeps a mutable borrow on the heap to optimize
1169+
/// its implementation.
11641170
///
11651171
/// # Examples
11661172
///

alloc/src/collections/vec_deque/mod.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -1215,21 +1215,25 @@ impl<T, A: Allocator> VecDeque<T, A> {
12151215
unsafe { IterMut::new(ring, tail, head, PhantomData) }
12161216
}
12171217

1218-
/// Creates a draining iterator that removes the specified range in the
1219-
/// deque and yields the removed items.
1218+
/// Removes the specified range from the deque in bulk, returning all
1219+
/// removed elements as an iterator. If the iterator is dropped before
1220+
/// being fully consumed, it drops the remaining removed elements.
12201221
///
1221-
/// Note 1: The element range is removed even if the iterator is not
1222-
/// consumed until the end.
1222+
/// The returned iterator keeps a mutable borrow on the queue to optimize
1223+
/// its implementation.
12231224
///
1224-
/// Note 2: It is unspecified how many elements are removed from the deque,
1225-
/// if the `Drain` value is not dropped, but the borrow it holds expires
1226-
/// (e.g., due to `mem::forget`).
12271225
///
12281226
/// # Panics
12291227
///
12301228
/// Panics if the starting point is greater than the end point or if
12311229
/// the end point is greater than the length of the deque.
12321230
///
1231+
/// # Leaking
1232+
///
1233+
/// If the returned iterator goes out of scope without being dropped (due to
1234+
/// [`mem::forget`], for example), the deque may have lost and leaked
1235+
/// elements arbitrarily, including elements outside the range.
1236+
///
12331237
/// # Examples
12341238
///
12351239
/// ```
@@ -1240,7 +1244,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
12401244
/// assert_eq!(drained, [3]);
12411245
/// assert_eq!(deque, [1, 2]);
12421246
///
1243-
/// // A full range clears all contents
1247+
/// // A full range clears all contents, like `clear()` does
12441248
/// deque.drain(..);
12451249
/// assert!(deque.is_empty());
12461250
/// ```

alloc/src/string.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -1628,17 +1628,24 @@ impl String {
16281628
self.vec.clear()
16291629
}
16301630

1631-
/// Creates a draining iterator that removes the specified range in the `String`
1632-
/// and yields the removed `chars`.
1631+
/// Removes the specified range from the string in bulk, returning all
1632+
/// removed characters as an iterator.
16331633
///
1634-
/// Note: The element range is removed even if the iterator is not
1635-
/// consumed until the end.
1634+
/// The returned iterator keeps a mutable borrow on the string to optimize
1635+
/// its implementation.
16361636
///
16371637
/// # Panics
16381638
///
16391639
/// Panics if the starting point or end point do not lie on a [`char`]
16401640
/// boundary, or if they're out of bounds.
16411641
///
1642+
/// # Leaking
1643+
///
1644+
/// If the returned iterator goes out of scope without being dropped (due to
1645+
/// [`core::mem::forget`], for example), the string may still contain a copy
1646+
/// of any drained characters, or may have lost characters arbitrarily,
1647+
/// including characters outside the range.
1648+
///
16421649
/// # Examples
16431650
///
16441651
/// Basic usage:
@@ -1652,7 +1659,7 @@ impl String {
16521659
/// assert_eq!(t, "α is alpha, ");
16531660
/// assert_eq!(s, "β is beta");
16541661
///
1655-
/// // A full range clears the string
1662+
/// // A full range clears the string, like `clear()` does
16561663
/// s.drain(..);
16571664
/// assert_eq!(s, "");
16581665
/// ```

alloc/src/vec/mod.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1799,19 +1799,24 @@ impl<T, A: Allocator> Vec<T, A> {
17991799
self.len += count;
18001800
}
18011801

1802-
/// Creates a draining iterator that removes the specified range in the vector
1803-
/// and yields the removed items.
1802+
/// Removes the specified range from the vector in bulk, returning all
1803+
/// removed elements as an iterator. If the iterator is dropped before
1804+
/// being fully consumed, it drops the remaining removed elements.
18041805
///
1805-
/// When the iterator **is** dropped, all elements in the range are removed
1806-
/// from the vector, even if the iterator was not fully consumed. If the
1807-
/// iterator **is not** dropped (with [`mem::forget`] for example), it is
1808-
/// unspecified how many elements are removed.
1806+
/// The returned iterator keeps a mutable borrow on the vector to optimize
1807+
/// its implementation.
18091808
///
18101809
/// # Panics
18111810
///
18121811
/// Panics if the starting point is greater than the end point or if
18131812
/// the end point is greater than the length of the vector.
18141813
///
1814+
/// # Leaking
1815+
///
1816+
/// If the returned iterator goes out of scope without being dropped (due to
1817+
/// [`mem::forget`], for example), the vector may have lost and leaked
1818+
/// elements arbitrarily, including elements outside the range.
1819+
///
18151820
/// # Examples
18161821
///
18171822
/// ```
@@ -1820,7 +1825,7 @@ impl<T, A: Allocator> Vec<T, A> {
18201825
/// assert_eq!(v, &[1]);
18211826
/// assert_eq!(u, &[2, 3]);
18221827
///
1823-
/// // A full range clears the vector
1828+
/// // A full range clears the vector, like `clear()` does
18241829
/// v.drain(..);
18251830
/// assert_eq!(v, &[]);
18261831
/// ```

core/tests/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![feature(bool_to_option)]
77
#![feature(box_syntax)]
88
#![feature(cell_update)]
9-
#![feature(cfg_panic)]
9+
#![cfg_attr(bootstrap, feature(cfg_panic))]
1010
#![cfg_attr(bootstrap, feature(cfg_target_has_atomic))]
1111
#![feature(const_assume)]
1212
#![feature(const_black_box)]

std/src/collections/hash/map.rs

+4
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,10 @@ impl<K, V, S> HashMap<K, V, S> {
547547
/// Clears the map, returning all key-value pairs as an iterator. Keeps the
548548
/// allocated memory for reuse.
549549
///
550+
/// If the returned iterator is dropped before being fully consumed, it
551+
/// drops the remaining key-value pairs. The returned iterator keeps a
552+
/// mutable borrow on the vector to optimize its implementation.
553+
///
550554
/// # Examples
551555
///
552556
/// ```

std/src/collections/hash/set.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,12 @@ impl<T, S> HashSet<T, S> {
227227
self.base.is_empty()
228228
}
229229

230-
/// Clears the set, returning all elements in an iterator.
230+
/// Clears the set, returning all elements as an iterator. Keeps the
231+
/// allocated memory for reuse.
232+
///
233+
/// If the returned iterator is dropped before being fully consumed, it
234+
/// drops the remaining elements. The returned iterator keeps a mutable
235+
/// borrow on the vector to optimize its implementation.
231236
///
232237
/// # Examples
233238
///

std/src/ffi/c_str.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ impl CString {
382382
let bytes: Vec<u8> = self.into();
383383
match memchr::memchr(0, &bytes) {
384384
Some(i) => Err(NulError(i, bytes)),
385-
None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
385+
None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }),
386386
}
387387
}
388388
}
@@ -405,7 +405,7 @@ impl CString {
405405
// This allows better optimizations if lto enabled.
406406
match memchr::memchr(0, bytes) {
407407
Some(i) => Err(NulError(i, buffer)),
408-
None => Ok(unsafe { CString::from_vec_unchecked(buffer) }),
408+
None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }),
409409
}
410410
}
411411

@@ -451,10 +451,15 @@ impl CString {
451451
/// ```
452452
#[must_use]
453453
#[stable(feature = "rust1", since = "1.0.0")]
454-
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
454+
pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self {
455+
debug_assert!(memchr::memchr(0, &v).is_none());
456+
unsafe { Self::_from_vec_unchecked(v) }
457+
}
458+
459+
unsafe fn _from_vec_unchecked(mut v: Vec<u8>) -> Self {
455460
v.reserve_exact(1);
456461
v.push(0);
457-
CString { inner: v.into_boxed_slice() }
462+
Self { inner: v.into_boxed_slice() }
458463
}
459464

460465
/// Retakes ownership of a `CString` that was transferred to C via
@@ -578,7 +583,7 @@ impl CString {
578583
pub fn into_string(self) -> Result<String, IntoStringError> {
579584
String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
580585
error: e.utf8_error(),
581-
inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
586+
inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) },
582587
})
583588
}
584589

@@ -735,6 +740,11 @@ impl CString {
735740
#[must_use]
736741
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
737742
pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
743+
debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len());
744+
unsafe { Self::_from_vec_with_nul_unchecked(v) }
745+
}
746+
747+
unsafe fn _from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
738748
Self { inner: v.into_boxed_slice() }
739749
}
740750

@@ -778,7 +788,7 @@ impl CString {
778788
Some(nul_pos) if nul_pos + 1 == v.len() => {
779789
// SAFETY: We know there is only one nul byte, at the end
780790
// of the vec.
781-
Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
791+
Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) })
782792
}
783793
Some(nul_pos) => Err(FromVecWithNulError {
784794
error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
@@ -811,7 +821,7 @@ impl ops::Deref for CString {
811821

812822
#[inline]
813823
fn deref(&self) -> &CStr {
814-
unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
824+
unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
815825
}
816826
}
817827

@@ -928,7 +938,7 @@ impl From<Vec<NonZeroU8>> for CString {
928938
};
929939
// SAFETY: `v` cannot contain null bytes, given the type-level
930940
// invariant of `NonZeroU8`.
931-
CString::from_vec_unchecked(v)
941+
Self::_from_vec_unchecked(v)
932942
}
933943
}
934944
}
@@ -1225,7 +1235,7 @@ impl CStr {
12251235
unsafe {
12261236
let len = sys::strlen(ptr);
12271237
let ptr = ptr as *const u8;
1228-
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
1238+
Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
12291239
}
12301240
}
12311241

@@ -1268,7 +1278,7 @@ impl CStr {
12681278
Some(nul_pos) if nul_pos + 1 == bytes.len() => {
12691279
// SAFETY: We know there is only one nul byte, at the end
12701280
// of the byte slice.
1271-
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
1281+
Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) })
12721282
}
12731283
Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
12741284
None => Err(FromBytesWithNulError::not_nul_terminated()),
@@ -1297,12 +1307,19 @@ impl CStr {
12971307
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
12981308
#[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
12991309
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
1310+
// We're in a const fn, so this is the best we can do
1311+
debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
1312+
unsafe { Self::_from_bytes_with_nul_unchecked(bytes) }
1313+
}
1314+
1315+
#[inline]
1316+
const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
13001317
// SAFETY: Casting to CStr is safe because its internal representation
13011318
// is a [u8] too (safe only inside std).
13021319
// Dereferencing the obtained pointer is safe because it comes from a
13031320
// reference. Making a reference is then safe because its lifetime
13041321
// is bound by the lifetime of the given `bytes`.
1305-
unsafe { &*(bytes as *const [u8] as *const CStr) }
1322+
unsafe { &*(bytes as *const [u8] as *const Self) }
13061323
}
13071324

13081325
/// Returns the inner pointer to this C string.
@@ -1566,7 +1583,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
15661583
// byte, since otherwise we could get an empty string that doesn't end
15671584
// in a null.
15681585
if index.start < bytes.len() {
1569-
unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
1586+
unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) }
15701587
} else {
15711588
panic!(
15721589
"index out of bounds: the len is {} but the index is {}",

std/src/ffi/c_str/tests.rs

-8
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ fn build_with_zero2() {
3232
assert!(CString::new(vec![0]).is_err());
3333
}
3434

35-
#[test]
36-
fn build_with_zero3() {
37-
unsafe {
38-
let s = CString::from_vec_unchecked(vec![0]);
39-
assert_eq!(s.as_bytes(), b"\0");
40-
}
41-
}
42-
4335
#[test]
4436
fn formatted() {
4537
let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();

0 commit comments

Comments
 (0)