diff options
Diffstat (limited to 'tests/ui/iterators')
46 files changed, 1491 insertions, 0 deletions
diff --git a/tests/ui/iterators/array-of-ranges.rs b/tests/ui/iterators/array-of-ranges.rs new file mode 100644 index 000000000..037540a3e --- /dev/null +++ b/tests/ui/iterators/array-of-ranges.rs @@ -0,0 +1,16 @@ +// check-pass + +fn main() { + for _ in [0..1] {} + for _ in [0..=1] {} + for _ in [0..] {} + for _ in [..1] {} + for _ in [..=1] {} + let start = 0; + let end = 0; + for _ in [start..end] {} + let array_of_range = [start..end]; + for _ in array_of_range {} + for _ in [0..1, 2..3] {} + for _ in [0..=1] {} +} diff --git a/tests/ui/iterators/array.rs b/tests/ui/iterators/array.rs new file mode 100644 index 000000000..5985c74e1 --- /dev/null +++ b/tests/ui/iterators/array.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() { + for _ in [1, 2] {} + let x = [1, 2]; + for _ in x {} + for _ in [1.0, 2.0] {} +} diff --git a/tests/ui/iterators/bound.rs b/tests/ui/iterators/bound.rs new file mode 100644 index 000000000..bdd99ef8d --- /dev/null +++ b/tests/ui/iterators/bound.rs @@ -0,0 +1,4 @@ +struct S<I: Iterator>(I); +struct T(S<u8>); +//~^ ERROR is not an iterator +fn main() {} diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr new file mode 100644 index 000000000..cc7ded498 --- /dev/null +++ b/tests/ui/iterators/bound.stderr @@ -0,0 +1,17 @@ +error[E0277]: `u8` is not an iterator + --> $DIR/bound.rs:2:10 + | +LL | struct T(S<u8>); + | ^^^^^ `u8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` +note: required by a bound in `S` + --> $DIR/bound.rs:1:13 + | +LL | struct S<I: Iterator>(I); + | ^^^^^^^^ required by this bound in `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/collect-into-array.rs b/tests/ui/iterators/collect-into-array.rs new file mode 100644 index 000000000..99d0d9bd7 --- /dev/null +++ b/tests/ui/iterators/collect-into-array.rs @@ -0,0 +1,6 @@ +fn main() { + let whatever: [u32; 10] = (0..10).collect(); + //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator + //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` + //~| NOTE required by a bound in `collect` +} diff --git a/tests/ui/iterators/collect-into-array.stderr b/tests/ui/iterators/collect-into-array.stderr new file mode 100644 index 000000000..e38745cc1 --- /dev/null +++ b/tests/ui/iterators/collect-into-array.stderr @@ -0,0 +1,13 @@ +error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator + --> $DIR/collect-into-array.rs:2:39 + | +LL | let whatever: [u32; 10] = (0..10).collect(); + | ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs new file mode 100644 index 000000000..5a8aacb1a --- /dev/null +++ b/tests/ui/iterators/collect-into-slice.rs @@ -0,0 +1,17 @@ +fn process_slice(data: &[i32]) { + todo!() +} + +fn main() { + let some_generated_vec = (0..10).collect(); + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size + //~| NOTE try explicitly collecting into a `Vec<{integer}>` + //~| NOTE required by a bound in `collect` + //~| NOTE required by a bound in `collect` + //~| NOTE all local variables must have a statically known size + //~| NOTE doesn't have a size known at compile-time + //~| NOTE doesn't have a size known at compile-time + process_slice(&some_generated_vec); +} diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr new file mode 100644 index 000000000..29fff8c51 --- /dev/null +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -0,0 +1,33 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:6:9 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:6:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size + --> $DIR/collect-into-slice.rs:6:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/float_iterator_hint.rs b/tests/ui/iterators/float_iterator_hint.rs new file mode 100644 index 000000000..a3335ca41 --- /dev/null +++ b/tests/ui/iterators/float_iterator_hint.rs @@ -0,0 +1,15 @@ +// #106728 + +fn main() { + for i in 0.2 { + //~^ ERROR `{float}` is not an iterator + //~| `{float}` is not an iterator + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + //~| NOTE required for `{float}` to implement `IntoIterator` + println!(); + } +} diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr new file mode 100644 index 000000000..bae23a1f8 --- /dev/null +++ b/tests/ui/iterators/float_iterator_hint.stderr @@ -0,0 +1,13 @@ +error[E0277]: `{float}` is not an iterator + --> $DIR/float_iterator_hint.rs:4:14 + | +LL | for i in 0.2 { + | ^^^ `{float}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{float}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{float}` to implement `IntoIterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/integral.rs b/tests/ui/iterators/integral.rs new file mode 100644 index 000000000..7537c7904 --- /dev/null +++ b/tests/ui/iterators/integral.rs @@ -0,0 +1,26 @@ +fn main() { + for _ in 42 {} + //~^ ERROR `{integer}` is not an iterator + for _ in 42 as u8 {} + //~^ ERROR `u8` is not an iterator + for _ in 42 as i8 {} + //~^ ERROR `i8` is not an iterator + for _ in 42 as u16 {} + //~^ ERROR `u16` is not an iterator + for _ in 42 as i16 {} + //~^ ERROR `i16` is not an iterator + for _ in 42 as u32 {} + //~^ ERROR `u32` is not an iterator + for _ in 42 as i32 {} + //~^ ERROR `i32` is not an iterator + for _ in 42 as u64 {} + //~^ ERROR `u64` is not an iterator + for _ in 42 as i64 {} + //~^ ERROR `i64` is not an iterator + for _ in 42 as usize {} + //~^ ERROR `usize` is not an iterator + for _ in 42 as isize {} + //~^ ERROR `isize` is not an iterator + for _ in 42.0 {} + //~^ ERROR `{float}` is not an iterator +} diff --git a/tests/ui/iterators/integral.stderr b/tests/ui/iterators/integral.stderr new file mode 100644 index 000000000..c142fec8d --- /dev/null +++ b/tests/ui/iterators/integral.stderr @@ -0,0 +1,123 @@ +error[E0277]: `{integer}` is not an iterator + --> $DIR/integral.rs:2:14 + | +LL | for _ in 42 {} + | ^^ `{integer}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{integer}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{integer}` to implement `IntoIterator` + +error[E0277]: `u8` is not an iterator + --> $DIR/integral.rs:4:14 + | +LL | for _ in 42 as u8 {} + | ^^^^^^^^ `u8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u8` to implement `IntoIterator` + +error[E0277]: `i8` is not an iterator + --> $DIR/integral.rs:6:14 + | +LL | for _ in 42 as i8 {} + | ^^^^^^^^ `i8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i8` to implement `IntoIterator` + +error[E0277]: `u16` is not an iterator + --> $DIR/integral.rs:8:14 + | +LL | for _ in 42 as u16 {} + | ^^^^^^^^^ `u16` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u16` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u16` to implement `IntoIterator` + +error[E0277]: `i16` is not an iterator + --> $DIR/integral.rs:10:14 + | +LL | for _ in 42 as i16 {} + | ^^^^^^^^^ `i16` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i16` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i16` to implement `IntoIterator` + +error[E0277]: `u32` is not an iterator + --> $DIR/integral.rs:12:14 + | +LL | for _ in 42 as u32 {} + | ^^^^^^^^^ `u32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u32` to implement `IntoIterator` + +error[E0277]: `i32` is not an iterator + --> $DIR/integral.rs:14:14 + | +LL | for _ in 42 as i32 {} + | ^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i32` to implement `IntoIterator` + +error[E0277]: `u64` is not an iterator + --> $DIR/integral.rs:16:14 + | +LL | for _ in 42 as u64 {} + | ^^^^^^^^^ `u64` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u64` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u64` to implement `IntoIterator` + +error[E0277]: `i64` is not an iterator + --> $DIR/integral.rs:18:14 + | +LL | for _ in 42 as i64 {} + | ^^^^^^^^^ `i64` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i64` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i64` to implement `IntoIterator` + +error[E0277]: `usize` is not an iterator + --> $DIR/integral.rs:20:14 + | +LL | for _ in 42 as usize {} + | ^^^^^^^^^^^ `usize` is not an iterator + | + = help: the trait `Iterator` is not implemented for `usize` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `usize` to implement `IntoIterator` + +error[E0277]: `isize` is not an iterator + --> $DIR/integral.rs:22:14 + | +LL | for _ in 42 as isize {} + | ^^^^^^^^^^^ `isize` is not an iterator + | + = help: the trait `Iterator` is not implemented for `isize` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `isize` to implement `IntoIterator` + +error[E0277]: `{float}` is not an iterator + --> $DIR/integral.rs:24:14 + | +LL | for _ in 42.0 {} + | ^^^^ `{float}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{float}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{float}` to implement `IntoIterator` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.rs b/tests/ui/iterators/into-iter-on-arrays-2018.rs new file mode 100644 index 000000000..60995170a --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2018.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2018 + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; +use std::slice::Iter; + +fn main() { + let array = [0; 10]; + + // Before 2021, the method dispatched to `IntoIterator for &[T; N]`, + // which we continue to support for compatibility. + let _: Iter<'_, i32> = array.into_iter(); + //~^ 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 + let _: Iter<'_, i32> = Array(array).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + // But you can always use the trait method explicitly as an array. + let _: IntoIter<i32, 10> = IntoIterator::into_iter(array); + + for _ in [1, 2, 3].into_iter() {} + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.stderr b/tests/ui/iterators/into-iter-on-arrays-2018.stderr new file mode 100644 index 000000000..2378476e5 --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2018.stderr @@ -0,0 +1,65 @@ +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 + | +LL | let _: Iter<'_, i32> = array.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + = note: `#[warn(array_into_iter)]` on by default +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | let _: Iter<'_, i32> = array.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 + | +LL | let _: Iter<'_, i32> = Rc::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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 + | +LL | let _: Iter<'_, i32> = Array(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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 + | +LL | for _ in [1, 2, 3].into_iter() {} + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | for _ in [1, 2, 3].iter() {} + | ~~~~ +help: or remove `.into_iter()` to iterate by value + | +LL - for _ in [1, 2, 3].into_iter() {} +LL + for _ in [1, 2, 3] {} + | + +warning: 5 warnings emitted + diff --git a/tests/ui/iterators/into-iter-on-arrays-2021.rs b/tests/ui/iterators/into-iter-on-arrays-2021.rs new file mode 100644 index 000000000..158317efe --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2021.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2021 + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; + +fn main() { + let array = [0; 10]; + + // In 2021, the method dispatches to `IntoIterator for [T; N]`. + let _: IntoIter<i32, 10> = array.into_iter(); + let _: IntoIter<i32, 10> = Box::new(array).into_iter(); + + // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. + let _: IntoIter<i32, 10> = Rc::new(array).into_iter(); + let _: IntoIter<i32, 10> = Array(array).into_iter(); + + // You can always use the trait method explicitly as an array. + let _: IntoIter<i32, 10> = IntoIterator::into_iter(array); +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.fixed b/tests/ui/iterators/into-iter-on-arrays-lint.fixed new file mode 100644 index 000000000..6e02a7024 --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.fixed @@ -0,0 +1,63 @@ +// run-pass +// run-rustfix +// rustfix-only-machine-applicable + +#[allow(unused_must_use)] +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [1, 2].iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + big.iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [0u8; 33].iter(); + //~^ 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(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); + + #[allow(array_into_iter)] + [0, 1].into_iter(); +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.rs b/tests/ui/iterators/into-iter-on-arrays-lint.rs new file mode 100644 index 000000000..582d5cadd --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.rs @@ -0,0 +1,63 @@ +// run-pass +// run-rustfix +// rustfix-only-machine-applicable + +#[allow(unused_must_use)] +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [1, 2].into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + big.into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [0u8; 33].into_iter(); + //~^ 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(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); + + #[allow(array_into_iter)] + [0, 1].into_iter(); +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.stderr b/tests/ui/iterators/into-iter-on-arrays-lint.stderr new file mode 100644 index 000000000..2fde276fa --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.stderr @@ -0,0 +1,143 @@ +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:11:11 + | +LL | small.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + = note: `#[warn(array_into_iter)]` on by default +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | small.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(small); + | ++++++++++++++++++++++++ ~ + +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:14:12 + | +LL | [1, 2].into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [1, 2].iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter([1, 2]); + | ++++++++++++++++++++++++ ~ + +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:17:9 + | +LL | big.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | big.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(big); + | ++++++++++++++++++++++++ ~ + +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:20:15 + | +LL | [0u8; 33].into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [0u8; 33].iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html> + +warning: 12 warnings emitted + diff --git a/tests/ui/iterators/into-iterator-type-inference-shift.rs b/tests/ui/iterators/into-iterator-type-inference-shift.rs new file mode 100644 index 000000000..9151172fd --- /dev/null +++ b/tests/ui/iterators/into-iterator-type-inference-shift.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] +// Regression test for type inference failure around shifting. In this +// case, the iteration yields an isize, but we hadn't run the full type +// propagation yet, and so we just saw a type variable, yielding an +// error. + +// pretty-expanded FIXME #23616 + +trait IntoIterator { + type Iter: Iterator; + + fn into_iter(self) -> Self::Iter; +} + +impl<I> IntoIterator for I where I: Iterator { + type Iter = I; + + fn into_iter(self) -> I { + self + } +} + +fn desugared_for_loop_bad(byte: u8) -> u8 { + let mut result = 0; + let mut x = IntoIterator::into_iter(0..8); + let mut y = Iterator::next(&mut x); + let mut z = y.unwrap(); + byte >> z; + 1 +} + +fn main() {} diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs new file mode 100644 index 000000000..882a1d139 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs @@ -0,0 +1,4 @@ +fn main() { + let x = Some(()).iter().map(|()| 1).sum::<f32>(); + //~^ ERROR a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}` +} diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr new file mode 100644 index 000000000..3cb5e44c7 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr @@ -0,0 +1,24 @@ +error[E0277]: a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}` + --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:41 + | +LL | let x = Some(()).iter().map(|()| 1).sum::<f32>(); + | ^^^ value of type `f32` cannot be made by summing a `std::iter::Iterator<Item={integer}>` + | + = help: the trait `Sum<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Sum<A>`: + <f32 as Sum<&'a f32>> + <f32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:29 + | +LL | let x = Some(()).iter().map(|()| 1).sum::<f32>(); + | -------- ------ ^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here + | | | + | | `Iterator::Item` is `&()` here + | this expression has type `Option<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain.rs b/tests/ui/iterators/invalid-iterator-chain.rs new file mode 100644 index 000000000..ebdf33303 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain.rs @@ -0,0 +1,53 @@ +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let scores = vec![(0, 0)] + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::<i32>()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .map(|x| x as i64) + .filter(|x| *x > 0) + .map(|x| { x + 1 }) + .map(|x| { x; }) + .sum::<i32>(), //~ ERROR E0277 + ); + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .filter(|x| *x > 0.0) + .map(|x| { x + 1.0 }) + .sum::<i32>(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277 + println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec<i32> = f.collect(); //~ ERROR E0277 + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr new file mode 100644 index 000000000..f3dceca7e --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -0,0 +1,176 @@ +error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain.rs:6:7 + | +LL | i.collect() + | ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>` + | + = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>` + = help: the trait `FromIterator<T>` is implemented for `Vec<T>` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:4:26 + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> { + | ^^^^^^^^^^^ `Iterator::Item` is `&X` here +LL | let i = i.map(|x| x.clone()); + | ------------------ `Iterator::Item` remains `&X` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:15:27 + | +LL | println!("{}", scores.sum::<i32>()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum<&'a i32>> + <i32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:12:10 + | +LL | let scores = vec![(0, 0)] + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | .iter() + | ------ `Iterator::Item` is `&({integer}, {integer})` here +LL | .map(|(a, b)| { + | __________^ +LL | | a + b; +LL | | }); + | |__________^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:26:14 + | +LL | .sum::<i32>(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum<&'a i32>> + <i32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:25:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| x as f64) + | ----------------- `Iterator::Item` changed to `f64` here +LL | .map(|x| x as i64) + | ----------------- `Iterator::Item` changed to `i64` here +LL | .filter(|x| *x > 0) + | ------------------ `Iterator::Item` remains `i64` here +LL | .map(|x| { x + 1 }) + | ------------------ `Iterator::Item` remains `i64` here +LL | .map(|x| { x; }) + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` + --> $DIR/invalid-iterator-chain.rs:36:14 + | +LL | .sum::<i32>(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>` + | + = help: the trait `Sum<f64>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum<&'a i32>> + <i32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:33:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| x as f64) + | ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here +LL | .filter(|x| *x > 0.0) + | -------------------- `Iterator::Item` remains `f64` here +LL | .map(|x| { x + 1.0 }) + | -------------------- `Iterator::Item` remains `f64` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:38:54 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum<&'a i32>> + <i32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:38:38 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); + | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here + | | | + | | `Iterator::Item` is `&{integer}` here + | this expression has type `Vec<{integer}>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` + --> $DIR/invalid-iterator-chain.rs:39:40 + | +LL | println!("{}", vec![(), ()].iter().sum::<i32>()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>` + | + = help: the trait `Sum<&()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum<&'a i32>> + <i32 as Sum> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:39:33 + | +LL | println!("{}", vec![(), ()].iter().sum::<i32>()); + | ------------ ^^^^^^ `Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:48:25 + | +LL | let g: Vec<i32> = f.collect(); + | ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>` + = help: the trait `FromIterator<T>` is implemented for `Vec<T>` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:44:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ----------- `Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- `Iterator::Item` remains `{integer}` here +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- `Iterator::Item` remains `{integer}` here +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ `Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- `Iterator::Item` remains `()` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/issue-28098.rs b/tests/ui/iterators/issue-28098.rs new file mode 100644 index 000000000..80c77edae --- /dev/null +++ b/tests/ui/iterators/issue-28098.rs @@ -0,0 +1,31 @@ +fn main() { + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + for _ in false {} + //~^ ERROR `bool` is not an iterator + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + other() +} + +pub fn other() { + // check errors are still reported globally + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + for _ in false {} + //~^ ERROR `bool` is not an iterator +} diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr new file mode 100644 index 000000000..3256e57d4 --- /dev/null +++ b/tests/ui/iterators/issue-28098.stderr @@ -0,0 +1,109 @@ +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `bool` is not an iterator + --> $DIR/issue-28098.rs:7:14 + | +LL | for _ in false {} + | ^^^^^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:10:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:10:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `bool` is not an iterator + --> $DIR/issue-28098.rs:29:14 + | +LL | for _ in false {} + | ^^^^^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/issue-58952-filter-type-length.rs b/tests/ui/iterators/issue-58952-filter-type-length.rs new file mode 100644 index 000000000..6d12db8d1 --- /dev/null +++ b/tests/ui/iterators/issue-58952-filter-type-length.rs @@ -0,0 +1,32 @@ +// run-pass +//! This snippet causes the type length to blowup exponentially, +//! so check that we don't accidentally exceed the type length limit. +// FIXME: Once the size of iterator adaptors is further reduced, +// increase the complexity of this test. +use std::collections::VecDeque; + +fn main() { + let c = 2; + let bv = vec![2]; + let b = bv + .iter() + .filter(|a| **a == c); + + let _a = vec![1, 2, 3] + .into_iter() + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .collect::<VecDeque<_>>(); +} diff --git a/tests/ui/iterators/iter-cloned-type-inference.rs b/tests/ui/iterators/iter-cloned-type-inference.rs new file mode 100644 index 000000000..898e33719 --- /dev/null +++ b/tests/ui/iterators/iter-cloned-type-inference.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(stable_features)] + +// Test to see that the element type of .cloned() can be inferred +// properly. Previously this would fail to deduce the type of `sum`. + +#![feature(iter_arith)] + +fn square_sum(v: &[i64]) -> i64 { + let sum: i64 = v.iter().cloned().sum(); + sum * sum +} + +fn main() { + assert_eq!(36, square_sum(&[1,2,3])); +} diff --git a/tests/ui/iterators/iter-count-overflow-debug.rs b/tests/ui/iterators/iter-count-overflow-debug.rs new file mode 100644 index 000000000..8e59c11e9 --- /dev/null +++ b/tests/ui/iterators/iter-count-overflow-debug.rs @@ -0,0 +1,15 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// needs-unwind +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; + +fn main() { + assert_eq!((0..usize::MAX).by_ref().count(), usize::MAX); + + let r = panic::catch_unwind(|| { + (0..=usize::MAX).by_ref().count() + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-count-overflow-ndebug.rs b/tests/ui/iterators/iter-count-overflow-ndebug.rs new file mode 100644 index 000000000..dcaaff671 --- /dev/null +++ b/tests/ui/iterators/iter-count-overflow-ndebug.rs @@ -0,0 +1,8 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +fn main() { + assert_eq!((0..usize::MAX).by_ref().count(), usize::MAX); + assert_eq!((0..=usize::MAX).by_ref().count(), 0); +} diff --git a/tests/ui/iterators/iter-map-fold-type-length.rs b/tests/ui/iterators/iter-map-fold-type-length.rs new file mode 100644 index 000000000..8ce4fcd87 --- /dev/null +++ b/tests/ui/iterators/iter-map-fold-type-length.rs @@ -0,0 +1,38 @@ +// run-pass +//! Check that type lengths don't explode with `Map` folds. +//! +//! The normal limit is a million, and this test used to exceed 1.5 million, but +//! now we can survive an even tighter limit. Still seems excessive though... +#![type_length_limit = "256000"] + +// Custom wrapper so Iterator methods aren't specialized. +struct Iter<I>(I); + +impl<I> Iterator for Iter<I> +where + I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next() + } +} + +fn main() { + let c = Iter(0i32..10) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .count(); + assert_eq!(c, 10); +} diff --git a/tests/ui/iterators/iter-position-overflow-debug.rs b/tests/ui/iterators/iter-position-overflow-debug.rs new file mode 100644 index 000000000..7a871e744 --- /dev/null +++ b/tests/ui/iterators/iter-position-overflow-debug.rs @@ -0,0 +1,21 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// needs-unwind +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; + +fn main() { + let n = usize::MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(usize::MAX)); + + let r = panic::catch_unwind(|| { + (0..).by_ref().position(|i| i > n) + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + (0..=n + 1).by_ref().position(|_| false) + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-position-overflow-ndebug.rs b/tests/ui/iterators/iter-position-overflow-ndebug.rs new file mode 100644 index 000000000..e610c3559 --- /dev/null +++ b/tests/ui/iterators/iter-position-overflow-ndebug.rs @@ -0,0 +1,10 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +fn main() { + let n = usize::MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(usize::MAX)); + assert_eq!((0..).by_ref().position(|i| i > n), Some(0)); + assert_eq!((0..=n + 1).by_ref().position(|_| false), None); +} diff --git a/tests/ui/iterators/iter-range.rs b/tests/ui/iterators/iter-range.rs new file mode 100644 index 000000000..993d93790 --- /dev/null +++ b/tests/ui/iterators/iter-range.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn range_<F>(a: isize, b: isize, mut it: F) where F: FnMut(isize) { + assert!((a < b)); + let mut i: isize = a; + while i < b { it(i); i += 1; } +} + +pub fn main() { + let mut sum: isize = 0; + range_(0, 100, |x| sum += x ); + println!("{}", sum); +} diff --git a/tests/ui/iterators/iter-step-overflow-debug.rs b/tests/ui/iterators/iter-step-overflow-debug.rs new file mode 100644 index 000000000..6aa349ebe --- /dev/null +++ b/tests/ui/iterators/iter-step-overflow-debug.rs @@ -0,0 +1,21 @@ +// run-pass +// needs-unwind +// compile-flags: -C debug_assertions=yes + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + let mut it = u8::MAX..; + it.next().unwrap(); // 255 + it.next().unwrap(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + let mut it = i8::MAX..; + it.next().unwrap(); // 127 + it.next().unwrap(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-step-overflow-ndebug.rs b/tests/ui/iterators/iter-step-overflow-ndebug.rs new file mode 100644 index 000000000..33e708769 --- /dev/null +++ b/tests/ui/iterators/iter-step-overflow-ndebug.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: -C debug_assertions=no + +fn main() { + let mut it = u8::MAX..; + assert_eq!(it.next().unwrap(), 255); + assert_eq!(it.next().unwrap(), u8::MIN); + + let mut it = i8::MAX..; + assert_eq!(it.next().unwrap(), 127); + assert_eq!(it.next().unwrap(), i8::MIN); +} diff --git a/tests/ui/iterators/iter-sum-overflow-debug.rs b/tests/ui/iterators/iter-sum-overflow-debug.rs new file mode 100644 index 000000000..24c764ff9 --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-debug.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind +// compile-flags: -C debug_assertions=yes + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().sum::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().product::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().cloned().sum::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().cloned().product::<i32>(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-sum-overflow-ndebug.rs b/tests/ui/iterators/iter-sum-overflow-ndebug.rs new file mode 100644 index 000000000..69f4744cc --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-ndebug.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -C debug_assertions=no + +fn main() { + assert_eq!([1i32, i32::MAX].iter().sum::<i32>(), + 1i32.wrapping_add(i32::MAX)); + assert_eq!([2i32, i32::MAX].iter().product::<i32>(), + 2i32.wrapping_mul(i32::MAX)); + + assert_eq!([1i32, i32::MAX].iter().cloned().sum::<i32>(), + 1i32.wrapping_add(i32::MAX)); + assert_eq!([2i32, i32::MAX].iter().cloned().product::<i32>(), + 2i32.wrapping_mul(i32::MAX)); +} diff --git a/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs b/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs new file mode 100644 index 000000000..be45c075d --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind +// compile-flags: -C overflow-checks + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().sum::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().product::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().cloned().sum::<i32>(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().cloned().product::<i32>(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/ranges.rs b/tests/ui/iterators/ranges.rs new file mode 100644 index 000000000..925d2d61a --- /dev/null +++ b/tests/ui/iterators/ranges.rs @@ -0,0 +1,9 @@ +fn main() { + for _ in ..10 {} + //~^ ERROR E0277 + for _ in ..=10 {} + //~^ ERROR E0277 + for _ in 0..10 {} + for _ in 0..=10 {} + for _ in 0.. {} +} diff --git a/tests/ui/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr new file mode 100644 index 000000000..b9fbcd530 --- /dev/null +++ b/tests/ui/iterators/ranges.stderr @@ -0,0 +1,23 @@ +error[E0277]: `RangeTo<{integer}>` is not an iterator + --> $DIR/ranges.rs:2:14 + | +LL | for _ in ..10 {} + | ^^^^ if you meant to iterate until a value, add a starting value + | + = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` + = note: required for `RangeTo<{integer}>` to implement `IntoIterator` + +error[E0277]: `RangeToInclusive<{integer}>` is not an iterator + --> $DIR/ranges.rs:4:14 + | +LL | for _ in ..=10 {} + | ^^^^^ if you meant to iterate until a value (including it), add a starting value + | + = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` + = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/rsplit-clone.rs b/tests/ui/iterators/rsplit-clone.rs new file mode 100644 index 000000000..911da7429 --- /dev/null +++ b/tests/ui/iterators/rsplit-clone.rs @@ -0,0 +1,11 @@ +// check-pass + +// RSplit<T, P> previously required T: Clone in order to be Clone + +struct NotClone; + +fn main() { + let elements = [NotClone, NotClone, NotClone]; + let rsplit = elements.rsplit(|_| false); + rsplit.clone(); +} diff --git a/tests/ui/iterators/skip-count-overflow.rs b/tests/ui/iterators/skip-count-overflow.rs new file mode 100644 index 000000000..64dee3e3c --- /dev/null +++ b/tests/ui/iterators/skip-count-overflow.rs @@ -0,0 +1,8 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C overflow-checks -C opt-level=3 + +fn main() { + let i = (0..usize::MAX).chain(0..10).skip(usize::MAX); + assert_eq!(i.count(), 10); +} diff --git a/tests/ui/iterators/string.rs b/tests/ui/iterators/string.rs new file mode 100644 index 000000000..ad58a463e --- /dev/null +++ b/tests/ui/iterators/string.rs @@ -0,0 +1,6 @@ +fn main() { + for _ in "".to_owned() {} + //~^ ERROR `String` is not an iterator + for _ in "" {} + //~^ ERROR `&str` is not an iterator +} diff --git a/tests/ui/iterators/string.stderr b/tests/ui/iterators/string.stderr new file mode 100644 index 000000000..ddfe0169b --- /dev/null +++ b/tests/ui/iterators/string.stderr @@ -0,0 +1,21 @@ +error[E0277]: `String` is not an iterator + --> $DIR/string.rs:2:14 + | +LL | for _ in "".to_owned() {} + | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` + | + = help: the trait `Iterator` is not implemented for `String` + = note: required for `String` to implement `IntoIterator` + +error[E0277]: `&str` is not an iterator + --> $DIR/string.rs:4:14 + | +LL | for _ in "" {} + | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` + | + = help: the trait `Iterator` is not implemented for `&str` + = note: required for `&str` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs new file mode 100644 index 000000000..42b5d36bf --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.rs @@ -0,0 +1,4 @@ +fn main() { + vec![true, false].map(|v| !v).collect::<Vec<_>>(); + //~^ ERROR `Vec<bool>` is not an iterator +} diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr new file mode 100644 index 000000000..a7d9c481a --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -0,0 +1,18 @@ +error[E0599]: `Vec<bool>` is not an iterator + --> $DIR/vec-on-unimplemented.rs:2:23 + | +LL | vec![true, false].map(|v| !v).collect::<Vec<_>>(); + | ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | + = note: doesn't satisfy `Vec<bool>: Iterator` + | + = note: the following trait bounds were not satisfied: + `Vec<bool>: Iterator` + which is required by `&mut Vec<bool>: Iterator` + `[bool]: Iterator` + which is required by `&mut [bool]: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. |