From e8de245532ff1af7741e3d808a4b7f5b312ebb45 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 02:51:07 +0100 Subject: [PATCH 1/8] Make `IndexRange` accessible from `alloc` Specifically make it public + unstable under `std_internals` + `doc(hidden)`. This is honestly Not Great, but I do not know a better solution :( --- library/core/src/ops/index_range.rs | 4 +++- library/core/src/ops/mod.rs | 4 +++- library/core/src/slice/index.rs | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index dce3514a1595b..0926711dcc110 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,3 +1,5 @@ +#![unstable(feature = "std_internals", issue = "none")] +#![doc(hidden)] use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZero; use crate::ub_checks; @@ -9,7 +11,7 @@ use crate::ub_checks; /// (Normal `Range` code needs to handle degenerate ranges like `10..0`, /// which takes extra checks compared to only handling the canonical form.) #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct IndexRange { +pub struct IndexRange { start: usize, end: usize, } diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 40526f9583e64..800ae51a9db7a 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -181,7 +181,9 @@ pub(crate) use self::drop::fallback_surface_drop; pub use self::function::{Fn, FnMut, FnOnce}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::index::{Index, IndexMut}; -pub(crate) use self::index_range::IndexRange; +#[doc(hidden)] +#[unstable(feature = "std_internals", issue = "none")] +pub use self::index_range::IndexRange; #[unstable(feature = "one_sided_range", issue = "69780")] pub use self::range::OneSidedRange; #[stable(feature = "inclusive_range", since = "1.26.0")] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index aafa19c0dd3d3..6239d40db2c33 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -149,6 +149,8 @@ mod private_slice_index { #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::RangeFrom {} + #[doc(hidden)] + #[unstable(feature = "std_internals", issue = "none")] impl Sealed for ops::IndexRange {} } @@ -283,6 +285,8 @@ unsafe impl SliceIndex<[T]> for usize { /// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here /// than there are for a general `Range` (which might be `100..3`). +#[doc(hidden)] +#[unstable(feature = "std_internals", issue = "none")] unsafe impl SliceIndex<[T]> for ops::IndexRange { type Output = [T]; From 4eb0c30b0ffeb1b7f11d142fb6949843b190198d Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 05:37:38 +0100 Subject: [PATCH 2/8] Add negative implementation of `Iterator` for `[&[mut]] Box<[T; N], A>` and `[T; N]` They'll be needed for `IntoIterator` impls. --- library/alloc/src/boxed/iter.rs | 15 +++++++++++++++ library/core/src/array/iter.rs | 3 +++ 2 files changed, 18 insertions(+) diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs index 90582aa49c6d7..c22daf4743aae 100644 --- a/library/alloc/src/boxed/iter.rs +++ b/library/alloc/src/boxed/iter.rs @@ -192,3 +192,18 @@ impl<'a> FromIterator> for Box { String::from_iter(iter).into_boxed_str() } } + +/// This implementation is required to make sure that the `Box<[I; N]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl !Iterator for Box<[I; N], A> {} + +/// This implementation is required to make sure that the `&Box<[I; N]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a Box<[I; N], A> {} + +/// This implementation is required to make sure that the `&mut Box<[I; N]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {} diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 9ce0eb61e0814..05f8e18343c00 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -35,6 +35,9 @@ pub struct IntoIter { alive: IndexRange, } +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl !Iterator for [T; N] {} + // Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator` // hides this implementation from explicit `.into_iter()` calls on editions < 2021, // so those calls will still resolve to the slice implementation, by reference. From 360042304838b6db9d21b1d0b8016b655776d106 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 05:41:06 +0100 Subject: [PATCH 3/8] Implement `IntoIterator` for `&[mut] Box<[T; N], A>` --- library/alloc/src/boxed/iter.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs index c22daf4743aae..451527a83f094 100644 --- a/library/alloc/src/boxed/iter.rs +++ b/library/alloc/src/boxed/iter.rs @@ -207,3 +207,21 @@ impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a Box<[I; N], A> {} /// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a Box<[T; N], A> { + type IntoIter = slice::Iter<'a, T>; + type Item = &'a T; + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a mut Box<[T; N], A> { + type IntoIter = slice::IterMut<'a, T>; + type Item = &'a mut T; + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} From f1ca4a5b941a2c46470effe367f3f74bc38569fd Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 02:55:39 +0100 Subject: [PATCH 4/8] Implement `IntoIterator` for `Box<[T; N], A>` --- library/alloc/src/boxed/iter.rs | 278 +++++++++++++++++++++++++++++++- 1 file changed, 275 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs index 451527a83f094..ca45eba5536ec 100644 --- a/library/alloc/src/boxed/iter.rs +++ b/library/alloc/src/boxed/iter.rs @@ -1,8 +1,11 @@ use core::async_iter::AsyncIterator; -use core::iter::FusedIterator; +use core::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; +use core::mem::MaybeUninit; +use core::num::NonZero; +use core::ops::IndexRange; use core::pin::Pin; -use core::slice; use core::task::{Context, Poll}; +use core::{ptr, slice}; use crate::alloc::Allocator; #[cfg(not(no_global_oom_handling))] @@ -10,9 +13,9 @@ use crate::borrow::Cow; use crate::boxed::Box; #[cfg(not(no_global_oom_handling))] use crate::string::String; -use crate::vec; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; +use crate::{fmt, vec}; #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Box { @@ -208,6 +211,275 @@ impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a Box<[I; N], A> {} #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {} +/// A by-value `Box<[T; N]>` iterator. +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +#[rustc_insignificant_dtor] +pub struct BoxedArrayIntoIter { + /// This is the array we are iterating over. + /// + /// Elements with index `i` where `alive.start <= i < alive.end` have not + /// been yielded yet and are valid array entries. Elements with indices `i + /// < alive.start` or `i >= alive.end` have been yielded already and must + /// not be accessed anymore! Those dead elements might even be in a + /// completely uninitialized state! + /// + /// So the invariants are: + /// - `data[alive]` is alive (i.e. contains valid elements) + /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the + /// elements were already read and must not be touched anymore!) + data: Box<[MaybeUninit; N], A>, + + /// The elements in `data` that have not been yielded yet. + /// + /// Invariants: + /// - `alive.end <= N` + /// + /// (And the `IndexRange` type requires `alive.start <= alive.end`.) + alive: IndexRange, +} + +impl BoxedArrayIntoIter { + /// Returns an immutable slice of all elements that have not been yielded + /// yet. + #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] + pub fn as_slice(&self) -> &[T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked(self.alive.clone()); + MaybeUninit::slice_assume_init_ref(slice) + } + } + + /// Returns a mutable slice of all elements that have not been yielded yet. + #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked_mut(self.alive.clone()); + MaybeUninit::slice_assume_init_mut(slice) + } + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl Iterator for BoxedArrayIntoIter { + type Item = T; + fn next(&mut self) -> Option { + // Get the next index from the front. + // + // Increasing `alive.start` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. + self.alive.next().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the start of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn fold(mut self, init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let data = &mut self.data; + iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) + } + + fn count(self) -> usize { + self.len() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the start, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_prefix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: The caller must provide an idx that is in bound of the remainder. + unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::().read() } + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl DoubleEndedIterator for BoxedArrayIntoIter { + fn next_back(&mut self) -> Option { + // Get the next index from the back. + // + // Decreasing `alive.end` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. + self.alive.next_back().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the end of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + fn rfold(mut self, init: Acc, mut rfold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let data = &mut self.data; + iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the end, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_suffix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl Drop for BoxedArrayIntoIter { + fn drop(&mut self) { + // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice + // of elements that have not been moved out yet and that remain + // to be dropped. + unsafe { ptr::drop_in_place(self.as_mut_slice()) } + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl ExactSizeIterator for BoxedArrayIntoIter { + fn len(&self) -> usize { + self.alive.len() + } + fn is_empty(&self) -> bool { + self.alive.is_empty() + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl FusedIterator for BoxedArrayIntoIter {} + +// The iterator indeed reports the correct length. The number of "alive" +// elements (that will still be yielded) is the length of the range `alive`. +// This range is decremented in length in either `next` or `next_back`. It is +// always decremented by 1 in those methods, but only if `Some(_)` is returned. +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +unsafe impl TrustedLen for BoxedArrayIntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + +// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive +// and thus we can't implement drop-handling +#[unstable(issue = "none", feature = "std_internals")] +impl NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +unsafe impl TrustedRandomAccessNoCoerce + for BoxedArrayIntoIter +where + T: NonDrop, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl Clone for BoxedArrayIntoIter { + fn clone(&self) -> Self { + // Note, we don't really need to match the exact same alive range, so + // we can just clone into offset 0 regardless of where `self` is. + + let mut new = Self { + data: Box::new_in( + [const { MaybeUninit::uninit() }; N], + Box::allocator(&self.data).clone(), + ), + alive: IndexRange::zero_to(0), + }; + + // Clone all alive elements. + for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { + // Write a clone into the new array, then update its alive range. + // If cloning panics, we'll correctly drop the previous items. + dst.write(src.clone()); + // This addition cannot overflow as we're iterating a slice + new.alive = IndexRange::zero_to(new.alive.end() + 1); + } + + new + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for BoxedArrayIntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Only print the elements that were not yielded yet: we cannot + // access the yielded elements anymore. + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +impl IntoIterator for Box<[T; N], A> { + type IntoIter = BoxedArrayIntoIter; + type Item = T; + fn into_iter(self) -> BoxedArrayIntoIter { + // SAFETY: This essentially does a transmute of `[T; N]` -> `[MaybeUninit; N]`, + // this is explicitly allowed as by the `MaybeUninit` docs. + let data = unsafe { + let (ptr, alloc) = Box::into_non_null_with_allocator(self); + Box::from_non_null_in(ptr.cast(), alloc) + }; + BoxedArrayIntoIter { data, alive: IndexRange::zero_to(N) } + } +} + #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a Box<[T; N], A> { type IntoIter = slice::Iter<'a, T>; From a7374b827a770d24c51ddf734a3820476c580a60 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 20:32:32 +0100 Subject: [PATCH 5/8] Add reexport of `Box<[T; N]>::Iter`, add `A = Global` default to it --- library/alloc/src/boxed.rs | 2 ++ library/alloc/src/boxed/iter.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e0f94428cfa65..a79ba9f2ad211 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -215,6 +215,8 @@ mod iter; /// [`ThinBox`] implementation. mod thin; +#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] +pub use iter::BoxedArrayIntoIter; #[unstable(feature = "thin_box", issue = "92791")] pub use thin::ThinBox; diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs index ca45eba5536ec..98080f601b6b6 100644 --- a/library/alloc/src/boxed/iter.rs +++ b/library/alloc/src/boxed/iter.rs @@ -7,7 +7,7 @@ use core::pin::Pin; use core::task::{Context, Poll}; use core::{ptr, slice}; -use crate::alloc::Allocator; +use crate::alloc::{Allocator, Global}; #[cfg(not(no_global_oom_handling))] use crate::borrow::Cow; use crate::boxed::Box; @@ -214,7 +214,7 @@ impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> { /// A by-value `Box<[T; N]>` iterator. #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] #[rustc_insignificant_dtor] -pub struct BoxedArrayIntoIter { +pub struct BoxedArrayIntoIter { /// This is the array we are iterating over. /// /// Elements with index `i` where `alive.start <= i < alive.end` have not From 7a5350824458dac34d796a2f5689149abc9c9c98 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 8 Dec 2024 20:31:13 +0100 Subject: [PATCH 6/8] Bless tests Note: this removes warnings, as this breakage was deemed acceptable, see --- .../ui/iterators/into-iter-on-arrays-2018.rs | 5 +- .../iterators/into-iter-on-arrays-2018.stderr | 19 ++--- .../ui/iterators/into-iter-on-arrays-2021.rs | 3 +- .../iterators/into-iter-on-arrays-lint.fixed | 32 ++------ .../ui/iterators/into-iter-on-arrays-lint.rs | 16 ---- .../iterators/into-iter-on-arrays-lint.stderr | 74 +------------------ 6 files changed, 18 insertions(+), 131 deletions(-) diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.rs b/tests/ui/iterators/into-iter-on-arrays-2018.rs index d23544052362f..2999d085c8738 100644 --- a/tests/ui/iterators/into-iter-on-arrays-2018.rs +++ b/tests/ui/iterators/into-iter-on-arrays-2018.rs @@ -5,6 +5,7 @@ use std::array::IntoIter; use std::ops::Deref; use std::rc::Rc; use std::slice::Iter; +use std::boxed::BoxedArrayIntoIter; fn main() { let array = [0; 10]; @@ -15,9 +16,7 @@ fn main() { //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning - let _: Iter<'_, i32> = Box::new(array).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning + let _: BoxedArrayIntoIter = Box::new(array).into_iter(); let _: Iter<'_, i32> = Rc::new(array).into_iter(); //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.stderr b/tests/ui/iterators/into-iter-on-arrays-2018.stderr index 9d6bbf06c36bb..eef7a4323898b 100644 --- a/tests/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/tests/ui/iterators/into-iter-on-arrays-2018.stderr @@ -1,5 +1,5 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-2018.rs:14:34 + --> $DIR/into-iter-on-arrays-2018.rs:15:34 | LL | let _: Iter<'_, i32> = array.into_iter(); | ^^^^^^^^^ @@ -17,16 +17,7 @@ LL | let _: Iter<'_, i32> = IntoIterator::into_iter(array); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-2018.rs:18:44 - | -LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-2018.rs:22:43 + --> $DIR/into-iter-on-arrays-2018.rs:21:43 | LL | let _: Iter<'_, i32> = Rc::new(array).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -35,7 +26,7 @@ LL | let _: Iter<'_, i32> = Rc::new(array).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-2018.rs:25:41 + --> $DIR/into-iter-on-arrays-2018.rs:24:41 | LL | let _: Iter<'_, i32> = Array(array).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -44,7 +35,7 @@ LL | let _: Iter<'_, i32> = Array(array).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-2018.rs:32:24 + --> $DIR/into-iter-on-arrays-2018.rs:31:24 | LL | for _ in [1, 2, 3].into_iter() {} | ^^^^^^^^^ @@ -61,5 +52,5 @@ LL - for _ in [1, 2, 3].into_iter() {} LL + for _ in [1, 2, 3] {} | -warning: 5 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/iterators/into-iter-on-arrays-2021.rs b/tests/ui/iterators/into-iter-on-arrays-2021.rs index 1bda0ebf6cb8e..918cc4cf0801f 100644 --- a/tests/ui/iterators/into-iter-on-arrays-2021.rs +++ b/tests/ui/iterators/into-iter-on-arrays-2021.rs @@ -4,13 +4,14 @@ use std::array::IntoIter; use std::ops::Deref; use std::rc::Rc; +use std::boxed::BoxedArrayIntoIter; fn main() { let array = [0; 10]; // In 2021, the method dispatches to `IntoIterator for [T; N]`. let _: IntoIter = array.into_iter(); - let _: IntoIter = Box::new(array).into_iter(); + let _: BoxedArrayIntoIter = Box::new(array).into_iter(); // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. let _: IntoIter = Rc::new(array).into_iter(); diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.fixed b/tests/ui/iterators/into-iter-on-arrays-lint.fixed index be754a28ffa92..51e18911ae743 100644 --- a/tests/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/tests/ui/iterators/into-iter-on-arrays-lint.fixed @@ -21,31 +21,15 @@ fn main() { //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning - Box::new(small).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new([1, 2]).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new(big).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new([0u8; 33]).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning + Box::new(small).into_iter(); + Box::new([1, 2]).into_iter(); + Box::new(big).into_iter(); + Box::new([0u8; 33]).into_iter(); - Box::new(Box::new(small)).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new(Box::new([1, 2])).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new(Box::new(big)).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning - Box::new(Box::new([0u8; 33])).iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning + Box::new(Box::new(small)).into_iter(); + Box::new(Box::new([1, 2])).into_iter(); + Box::new(Box::new(big)).into_iter(); + Box::new(Box::new([0u8; 33])).into_iter(); // Expressions that should not (&[1, 2]).into_iter(); diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.rs b/tests/ui/iterators/into-iter-on-arrays-lint.rs index e4dddb325cd37..59816f1d98ff5 100644 --- a/tests/ui/iterators/into-iter-on-arrays-lint.rs +++ b/tests/ui/iterators/into-iter-on-arrays-lint.rs @@ -22,30 +22,14 @@ fn main() { //~| WARNING this changes meaning Box::new(small).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new([1, 2]).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new(big).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new([0u8; 33]).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new(Box::new(small)).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new(Box::new([1, 2])).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new(Box::new(big)).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning Box::new(Box::new([0u8; 33])).into_iter(); - //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this changes meaning // Expressions that should not (&[1, 2]).into_iter(); diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.stderr b/tests/ui/iterators/into-iter-on-arrays-lint.stderr index da388d6b848de..f4974b839a8a8 100644 --- a/tests/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/tests/ui/iterators/into-iter-on-arrays-lint.stderr @@ -67,77 +67,5 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | IntoIterator::into_iter([0u8; 33]); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:24:21 - | -LL | Box::new(small).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:27:22 - | -LL | Box::new([1, 2]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:30:19 - | -LL | Box::new(big).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:33:25 - | -LL | Box::new([0u8; 33]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:37:31 - | -LL | Box::new(Box::new(small)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:40:32 - | -LL | Box::new(Box::new([1, 2])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:43:29 - | -LL | Box::new(Box::new(big)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:46:35 - | -LL | Box::new(Box::new([0u8; 33])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this changes meaning in Rust 2021 - = note: for more information, see - -warning: 12 warnings emitted +warning: 4 warnings emitted From 576e7045a935e1c065693c487e1ab0aca76b83ff Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 10 Dec 2024 01:56:29 +0100 Subject: [PATCH 7/8] move `doc(hidden)` i forgot that `#![doc(hidden)]` applies to the module, not everything in it... again. (this caused linkchecker to fail, because of a debug impl) --- library/core/src/ops/index_range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 0926711dcc110..f7eb68a9569ae 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,5 +1,4 @@ #![unstable(feature = "std_internals", issue = "none")] -#![doc(hidden)] use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZero; use crate::ub_checks; @@ -11,6 +10,7 @@ use crate::ub_checks; /// (Normal `Range` code needs to handle degenerate ranges like `10..0`, /// which takes extra checks compared to only handling the canonical form.) #[derive(Clone, Debug, PartialEq, Eq)] +#[doc(hidden)] pub struct IndexRange { start: usize, end: usize, From 6bcd9c3d5627d839253bf06428304b9e6157c1b9 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 16 Dec 2024 19:07:42 +0100 Subject: [PATCH 8/8] fixup `no_global_oom_handling` --- library/alloc/src/boxed/iter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs index 98080f601b6b6..a27e6c2d76282 100644 --- a/library/alloc/src/boxed/iter.rs +++ b/library/alloc/src/boxed/iter.rs @@ -429,6 +429,7 @@ where const MAY_HAVE_SIDE_EFFECT: bool = false; } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")] impl Clone for BoxedArrayIntoIter { fn clone(&self) -> Self {