From df0bf5ed991c5c75e06825022f5b2fabce3a8b84 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Apr 2024 22:43:48 -0400 Subject: [PATCH 1/2] Add `Box<[T; N]>: IntoIterator` --- library/alloc/src/boxed.rs | 47 ++++++++++++++++++++++++++++++++++ library/core/src/slice/iter.rs | 3 +++ 2 files changed, 50 insertions(+) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e5d62447eb20e..1e30f4cc41ed3 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -165,6 +165,7 @@ use core::ops::{ }; use core::pin::Pin; use core::ptr::{self, addr_of_mut, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] @@ -177,6 +178,7 @@ use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; #[cfg(not(no_global_oom_handling))] use crate::string::String; +use crate::vec; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; @@ -2080,6 +2082,51 @@ impl FromIterator for Box<[I]> { } } +/// 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_slice_into_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_slice_into_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_slice_into_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {} + +// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2024, +// so those calls will still resolve to the slice implementation, by reference. +#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")] +impl IntoIterator for Box<[I; N], A> { + type IntoIter = vec::IntoIter; + type Item = I; + fn into_iter(self) -> vec::IntoIter { + (self as Box<[I], A>).into_vec().into_iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, I, const N: usize, A: Allocator> IntoIterator for &'a Box<[I; N], A> { + type IntoIter = slice::Iter<'a, I>; + type Item = &'a I; + fn into_iter(self) -> slice::Iter<'a, I> { + self.iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")] +impl<'a, I, const N: usize, A: Allocator> IntoIterator for &'a mut Box<[I; N], A> { + type IntoIter = slice::IterMut<'a, I>; + type Item = &'a mut I; + fn into_iter(self) -> slice::IterMut<'a, I> { + self.iter_mut() + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box<[T], A> { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index d7d4f90c1a538..b45cfcde9f134 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -16,6 +16,9 @@ use crate::ptr::{self, without_provenance, without_provenance_mut, NonNull}; use super::{from_raw_parts, from_raw_parts_mut}; +#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")] +impl !Iterator for [T; N] {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> IntoIterator for &'a [T] { type Item = &'a T; From bc77b581321afb6ec0cee064c8fe379f4f494bb2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 May 2024 14:27:42 -0400 Subject: [PATCH 2/2] Bless tests, remove tests that don't matter anymore --- .../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 | 4 +- .../iterators/into-iter-on-arrays-lint.fixed | 26 ------- .../ui/iterators/into-iter-on-arrays-lint.rs | 26 ------- .../iterators/into-iter-on-arrays-lint.stderr | 74 +------------------ .../method-on-unbounded-type-param.stderr | 4 +- 7 files changed, 12 insertions(+), 146 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..06a213636966b 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::vec; fn main() { let array = [0; 10]; @@ -15,10 +16,6 @@ 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 _: Iter<'_, i32> = Rc::new(array).into_iter(); //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.stderr b/tests/ui/iterators/into-iter-on-arrays-2018.stderr index 2378476e5d0e3..fae161713c9a2 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:19: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:22: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:29: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..3c019e045245f 100644 --- a/tests/ui/iterators/into-iter-on-arrays-2021.rs +++ b/tests/ui/iterators/into-iter-on-arrays-2021.rs @@ -4,13 +4,15 @@ use std::array::IntoIter; use std::ops::Deref; use std::rc::Rc; +use std::vec; 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(); + // and for `Box<[T; N]>`, we use `vec::IntoIter`, since #124108. + let _: vec::IntoIter = 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..9fa794714de27 100644 --- a/tests/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/tests/ui/iterators/into-iter-on-arrays-lint.fixed @@ -21,32 +21,6 @@ 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(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 - // Expressions that should not (&[1, 2]).into_iter(); (&small).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..4084fba1eabb2 100644 --- a/tests/ui/iterators/into-iter-on-arrays-lint.rs +++ b/tests/ui/iterators/into-iter-on-arrays-lint.rs @@ -21,32 +21,6 @@ fn main() { //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| 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(); (&small).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 2fde276faa3d5..ba5591c5429bb 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 diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index 4d968e7bee10f..0b1f83a9de928 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -76,8 +76,8 @@ LL | x.cmp(&x); which is required by `&mut dyn T: Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `cmp`, perhaps you need to implement one of them: - candidate #1: `Iterator` - candidate #2: `Ord` + candidate #1: `Ord` + = note: the trait `Iterator` defines an item `cmp`, but is explicitly unimplemented error: aborting due to 4 previous errors