Skip to content

Commit 31e8eee

Browse files
committed
Auto merge of rust-lang#146185 - Zalathar:rollup-n14lyv6, r=Zalathar
Rollup of 24 pull requests Successful merges: - rust-lang#140459 (Add `read_buf` equivalents for positioned reads) - rust-lang#143725 (core: add Peekable::next_if_map) - rust-lang#145209 (Stabilize `path_add_extension`) - rust-lang#145342 (fix drop scope for `super let` bindings within `if let`) - rust-lang#145750 (raw_vec.rs: Remove superfluous fn alloc_guard) - rust-lang#145827 (On unused binding or binding not present in all patterns, suggest potential typo of unit struct/variant or const) - rust-lang#145932 (Allow `inline(always)` with a target feature behind a unstable feature `target_feature_inline_always`.) - rust-lang#145962 (Ensure we emit an allocator shim when only some crate types need one) - rust-lang#145963 (Add LSX accelerated implementation for source file analysis) - rust-lang#146054 (add `#[must_use]` to `array::repeat`) - rust-lang#146090 (Derive `PartialEq` for `InvisibleOrigin`) - rust-lang#146112 (don't uppercase error messages) - rust-lang#146120 (Correct typo in `rustc_errors` comment) - rust-lang#146124 (Test `rustc-dev` in `distcheck`) - rust-lang#146127 (Rename `ToolRustc` to `ToolRustcPrivate`) - rust-lang#146131 (rustdoc-search: add test case for indexing every item type) - rust-lang#146134 (llvm: nvptx: Layout update to match LLVM) - rust-lang#146136 (docs(std): add missing closing code block fences in doc comments) - rust-lang#146137 (Disallow frontmatter in `--cfg` and `--check-cfg` arguments) - rust-lang#146140 (compiletest: cygwin follows windows in using PATH for dynamic libraries) - rust-lang#146150 (fix(rustdoc): match rustc `--emit` precedence ) - rust-lang#146155 (Make bootstrap self test parallel) - rust-lang#146161 ([rustdoc] Uncomment code to add scraped rustdoc examples in loaded paths) - rust-lang#146172 (triagebot: configure some pings when certain attributes are used) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 699fe87 + b95ef79 commit 31e8eee

File tree

21 files changed

+509
-57
lines changed

21 files changed

+509
-57
lines changed

alloc/src/raw_vec/mod.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,6 @@ impl<A: Allocator> RawVecInner<A> {
468468
return Ok(Self::new_in(alloc, elem_layout.alignment()));
469469
}
470470

471-
if let Err(err) = alloc_guard(layout.size()) {
472-
return Err(err);
473-
}
474-
475471
let result = match init {
476472
AllocInit::Uninitialized => alloc.allocate(layout),
477473
#[cfg(not(no_global_oom_handling))]
@@ -662,7 +658,7 @@ impl<A: Allocator> RawVecInner<A> {
662658
let new_layout = layout_array(cap, elem_layout)?;
663659

664660
let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
665-
// SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
661+
// SAFETY: layout_array would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
666662

667663
unsafe { self.set_ptr_and_cap(ptr, cap) };
668664
Ok(())
@@ -684,7 +680,7 @@ impl<A: Allocator> RawVecInner<A> {
684680
let new_layout = layout_array(cap, elem_layout)?;
685681

686682
let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
687-
// SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
683+
// SAFETY: layout_array would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
688684
unsafe {
689685
self.set_ptr_and_cap(ptr, cap);
690686
}
@@ -771,8 +767,6 @@ fn finish_grow<A>(
771767
where
772768
A: Allocator,
773769
{
774-
alloc_guard(new_layout.size())?;
775-
776770
let memory = if let Some((ptr, old_layout)) = current_memory {
777771
debug_assert_eq!(old_layout.align(), new_layout.align());
778772
unsafe {
@@ -799,23 +793,6 @@ fn handle_error(e: TryReserveError) -> ! {
799793
}
800794
}
801795

802-
// We need to guarantee the following:
803-
// * We don't ever allocate `> isize::MAX` byte-size objects.
804-
// * We don't overflow `usize::MAX` and actually allocate too little.
805-
//
806-
// On 64-bit we just need to check for overflow since trying to allocate
807-
// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
808-
// an extra guard for this in case we're running on a platform which can use
809-
// all 4GB in user-space, e.g., PAE or x32.
810-
#[inline]
811-
fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
812-
if usize::BITS < 64 && alloc_size > isize::MAX as usize {
813-
Err(CapacityOverflow.into())
814-
} else {
815-
Ok(())
816-
}
817-
}
818-
819796
#[inline]
820797
fn layout_array(cap: usize, elem_layout: Layout) -> Result<Layout, TryReserveError> {
821798
elem_layout.repeat(cap).map(|(layout, _pad)| layout).map_err(|_| CapacityOverflow.into())

core/src/array/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub use iter::IntoIter;
4848
/// assert_eq!(strings, ["Hello there!", "Hello there!"]);
4949
/// ```
5050
#[inline]
51+
#[must_use = "cloning is often expensive and is not expected to have side effects"]
5152
#[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")]
5253
pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
5354
from_trusted_iterator(repeat_n(val, N))

core/src/iter/adapters/chain.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ impl<A: Default, B: Default> Default for Chain<A, B> {
321321
///
322322
/// // take requires `Default`
323323
/// let _: Chain<_, _> = mem::take(&mut foo.0);
324+
/// ```
324325
fn default() -> Self {
325326
Chain::new(Default::default(), Default::default())
326327
}

core/src/iter/adapters/peekable.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,108 @@ impl<I: Iterator> Peekable<I> {
317317
{
318318
self.next_if(|next| next == expected)
319319
}
320+
321+
/// Consumes the next value of this iterator and applies a function `f` on it,
322+
/// returning the result if the closure returns `Ok`.
323+
///
324+
/// Otherwise if the closure returns `Err` the value is put back for the next iteration.
325+
///
326+
/// The content of the `Err` variant is typically the original value of the closure,
327+
/// but this is not required. If a different value is returned,
328+
/// the next `peek()` or `next()` call will result in this new value.
329+
/// This is similar to modifying the output of `peek_mut()`.
330+
///
331+
/// If the closure panics, the next value will always be consumed and dropped
332+
/// even if the panic is caught, because the closure never returned an `Err` value to put back.
333+
///
334+
/// # Examples
335+
///
336+
/// Parse the leading decimal number from an iterator of characters.
337+
/// ```
338+
/// #![feature(peekable_next_if_map)]
339+
/// let mut iter = "125 GOTO 10".chars().peekable();
340+
/// let mut line_num = 0_u32;
341+
/// while let Some(digit) = iter.next_if_map(|c| c.to_digit(10).ok_or(c)) {
342+
/// line_num = line_num * 10 + digit;
343+
/// }
344+
/// assert_eq!(line_num, 125);
345+
/// assert_eq!(iter.collect::<String>(), " GOTO 10");
346+
/// ```
347+
///
348+
/// Matching custom types.
349+
/// ```
350+
/// #![feature(peekable_next_if_map)]
351+
///
352+
/// #[derive(Debug, PartialEq, Eq)]
353+
/// enum Node {
354+
/// Comment(String),
355+
/// Red(String),
356+
/// Green(String),
357+
/// Blue(String),
358+
/// }
359+
///
360+
/// /// Combines all consecutive `Comment` nodes into a single one.
361+
/// fn combine_comments(nodes: Vec<Node>) -> Vec<Node> {
362+
/// let mut result = Vec::with_capacity(nodes.len());
363+
/// let mut iter = nodes.into_iter().peekable();
364+
/// let mut comment_text = None::<String>;
365+
/// loop {
366+
/// // Typically the closure in .next_if_map() matches on the input,
367+
/// // extracts the desired pattern into an `Ok`,
368+
/// // and puts the rest into an `Err`.
369+
/// while let Some(text) = iter.next_if_map(|node| match node {
370+
/// Node::Comment(text) => Ok(text),
371+
/// other => Err(other),
372+
/// }) {
373+
/// comment_text.get_or_insert_default().push_str(&text);
374+
/// }
375+
///
376+
/// if let Some(text) = comment_text.take() {
377+
/// result.push(Node::Comment(text));
378+
/// }
379+
/// if let Some(node) = iter.next() {
380+
/// result.push(node);
381+
/// } else {
382+
/// break;
383+
/// }
384+
/// }
385+
/// result
386+
/// }
387+
///# assert_eq!( // hiding the test to avoid cluttering the documentation.
388+
///# combine_comments(vec![
389+
///# Node::Comment("The".to_owned()),
390+
///# Node::Comment("Quick".to_owned()),
391+
///# Node::Comment("Brown".to_owned()),
392+
///# Node::Red("Fox".to_owned()),
393+
///# Node::Green("Jumped".to_owned()),
394+
///# Node::Comment("Over".to_owned()),
395+
///# Node::Blue("The".to_owned()),
396+
///# Node::Comment("Lazy".to_owned()),
397+
///# Node::Comment("Dog".to_owned()),
398+
///# ]),
399+
///# vec![
400+
///# Node::Comment("TheQuickBrown".to_owned()),
401+
///# Node::Red("Fox".to_owned()),
402+
///# Node::Green("Jumped".to_owned()),
403+
///# Node::Comment("Over".to_owned()),
404+
///# Node::Blue("The".to_owned()),
405+
///# Node::Comment("LazyDog".to_owned()),
406+
///# ],
407+
///# )
408+
/// ```
409+
#[unstable(feature = "peekable_next_if_map", issue = "143702")]
410+
pub fn next_if_map<R>(&mut self, f: impl FnOnce(I::Item) -> Result<R, I::Item>) -> Option<R> {
411+
let unpeek = if let Some(item) = self.next() {
412+
match f(item) {
413+
Ok(result) => return Some(result),
414+
Err(item) => Some(item),
415+
}
416+
} else {
417+
None
418+
};
419+
self.peeked = Some(unpeek);
420+
None
421+
}
320422
}
321423

322424
#[unstable(feature = "trusted_len", issue = "37572")]

core/src/num/int_macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,7 @@ macro_rules! int_impl {
12851285
///
12861286
/// ```should_panic
12871287
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")]
1288-
///
1288+
/// ```
12891289
#[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
12901290
#[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
12911291
#[must_use = "this returns the result of the operation, \

core/src/num/uint_macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ macro_rules! uint_impl {
16201620
///
16211621
/// ```should_panic
16221622
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")]
1623-
///
1623+
/// ```
16241624
#[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
16251625
#[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
16261626
#[must_use = "this returns the result of the operation, \

core/src/ops/range.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ pub trait RangeBounds<T: ?Sized> {
836836
/// assert!(!(0.0..1.0).contains(&f32::NAN));
837837
/// assert!(!(0.0..f32::NAN).contains(&0.5));
838838
/// assert!(!(f32::NAN..1.0).contains(&0.5));
839+
/// ```
839840
#[inline]
840841
#[stable(feature = "range_contains", since = "1.35.0")]
841842
fn contains<U>(&self, item: &U) -> bool

core/src/ptr/mut_ptr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl<T: PointeeSized> *mut T {
106106
///
107107
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
108108
/// println!("{:?}", unsafe { &*bad });
109+
/// ```
109110
#[unstable(feature = "set_ptr_value", issue = "75091")]
110111
#[must_use = "returns a new pointer rather than modifying its argument"]
111112
#[inline]

coretests/tests/iter/adapters/peekable.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,89 @@ fn test_peekable_non_fused() {
271271
assert_eq!(iter.peek(), None);
272272
assert_eq!(iter.next_back(), None);
273273
}
274+
275+
#[test]
276+
fn test_peekable_next_if_map_mutation() {
277+
fn collatz((mut num, mut len): (u64, u32)) -> Result<u32, (u64, u32)> {
278+
let jump = num.trailing_zeros();
279+
num >>= jump;
280+
len += jump;
281+
if num == 1 { Ok(len) } else { Err((3 * num + 1, len + 1)) }
282+
}
283+
284+
let mut iter = once((3, 0)).peekable();
285+
assert_eq!(iter.peek(), Some(&(3, 0)));
286+
assert_eq!(iter.next_if_map(collatz), None);
287+
assert_eq!(iter.peek(), Some(&(10, 1)));
288+
assert_eq!(iter.next_if_map(collatz), None);
289+
assert_eq!(iter.peek(), Some(&(16, 3)));
290+
assert_eq!(iter.next_if_map(collatz), Some(7));
291+
assert_eq!(iter.peek(), None);
292+
assert_eq!(iter.next_if_map(collatz), None);
293+
}
294+
295+
#[test]
296+
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
297+
fn test_peekable_next_if_map_panic() {
298+
use core::cell::Cell;
299+
use std::panic::{AssertUnwindSafe, catch_unwind};
300+
301+
struct BitsetOnDrop<'a> {
302+
value: u32,
303+
cell: &'a Cell<u32>,
304+
}
305+
impl<'a> Drop for BitsetOnDrop<'a> {
306+
fn drop(&mut self) {
307+
self.cell.update(|v| v | self.value);
308+
}
309+
}
310+
311+
let cell = &Cell::new(0);
312+
let mut it = [
313+
BitsetOnDrop { value: 1, cell },
314+
BitsetOnDrop { value: 2, cell },
315+
BitsetOnDrop { value: 4, cell },
316+
BitsetOnDrop { value: 8, cell },
317+
]
318+
.into_iter()
319+
.peekable();
320+
321+
// sanity check, .peek() won't consume the value, .next() will transfer ownership.
322+
let item = it.peek().unwrap();
323+
assert_eq!(item.value, 1);
324+
assert_eq!(cell.get(), 0);
325+
let item = it.next().unwrap();
326+
assert_eq!(item.value, 1);
327+
assert_eq!(cell.get(), 0);
328+
drop(item);
329+
assert_eq!(cell.get(), 1);
330+
331+
// next_if_map returning Ok should transfer the value out.
332+
let item = it.next_if_map(Ok).unwrap();
333+
assert_eq!(item.value, 2);
334+
assert_eq!(cell.get(), 1);
335+
drop(item);
336+
assert_eq!(cell.get(), 3);
337+
338+
// next_if_map returning Err should not drop anything.
339+
assert_eq!(it.next_if_map::<()>(Err), None);
340+
assert_eq!(cell.get(), 3);
341+
assert_eq!(it.peek().unwrap().value, 4);
342+
assert_eq!(cell.get(), 3);
343+
344+
// next_if_map panicking should consume and drop the item.
345+
let result = catch_unwind({
346+
let mut it = AssertUnwindSafe(&mut it);
347+
move || it.next_if_map::<()>(|_| panic!())
348+
});
349+
assert!(result.is_err());
350+
assert_eq!(cell.get(), 7);
351+
assert_eq!(it.next().unwrap().value, 8);
352+
assert_eq!(cell.get(), 15);
353+
assert!(it.peek().is_none());
354+
355+
// next_if_map should *not* execute the closure if the iterator is exhausted.
356+
assert!(it.next_if_map::<()>(|_| panic!()).is_none());
357+
assert!(it.peek().is_none());
358+
assert_eq!(cell.get(), 15);
359+
}

coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
#![feature(numfmt)]
8383
#![feature(option_reduce)]
8484
#![feature(pattern)]
85+
#![feature(peekable_next_if_map)]
8586
#![feature(pointer_is_aligned_to)]
8687
#![feature(portable_simd)]
8788
#![feature(ptr_metadata)]

0 commit comments

Comments
 (0)