diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-10-17 19:07:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-17 19:07:22 +0200 |
| commit | a5aa52c23a0c56341db040dcc63dc323ba41bb68 (patch) | |
| tree | 8f92e68242c3cd73c245eb994e6a3c97b148d82c /tests | |
| parent | ce407429dd978624310ae8a1cba9ab481fb8dae3 (diff) | |
| parent | 26954f60ffd4fa462b06edf05290104aa8cdbdc3 (diff) | |
| download | rust-a5aa52c23a0c56341db040dcc63dc323ba41bb68.tar.gz rust-a5aa52c23a0c56341db040dcc63dc323ba41bb68.zip | |
Rollup merge of #116717 - estebank:issue-9082, r=oli-obk
Special case iterator chain checks for suggestion When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`. Fix #9082.
Diffstat (limited to 'tests')
4 files changed, 267 insertions, 0 deletions
diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.fixed b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed new file mode 100644 index 00000000000..513b5bd13d8 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed @@ -0,0 +1,42 @@ +// run-rustfix +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> where X: Clone { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b + }); + println!("{}", scores.sum::<i32>()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x }) + .map(|x| { x }) + .sum::<i32>(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x }).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 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.rs b/tests/ui/iterators/invalid-iterator-chain-fixable.rs new file mode 100644 index 00000000000..79b861702c7 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.rs @@ -0,0 +1,42 @@ +// run-rustfix +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 v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::<i32>()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x; }) + .map(|x| { x }) + .sum::<i32>(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).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 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr new file mode 100644 index 00000000000..1bfe765e78a --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr @@ -0,0 +1,157 @@ +error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain-fixable.rs:7:7 + | +LL | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` +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<X>` is implemented for `Vec<X>` + = help: for that trait implementation, expected `X`, found `&X` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:5: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 +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> where X: Clone { + | ++++++++++++++ + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:17:33 + | +LL | println!("{}", scores.sum::<i32>()); + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum> + <i32 as Sum<&'a i32>> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:14:10 + | +LL | let v = vec![(0, 0)]; + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | let scores = v +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 +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:25:20 + | +LL | .sum::<i32>(), + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum> + <i32 as Sum<&'a i32>> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:23: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; }) + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here +LL | .map(|x| { x }) + | -------------- `Iterator::Item` remains `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:27:60 + | +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=()>` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum<A>`: + <i32 as Sum> + <i32 as Sum<&'a i32>> +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:27: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 +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::<i32>()); + | + +error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:36: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<i32>` is implemented for `Vec<i32>` + = help: for that trait implementation, expected `i32`, found `()` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:32: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 +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index 2601c9c0d69..4dc13086912 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -1,6 +1,8 @@ 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 | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` LL | i.collect() | ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>` | @@ -16,6 +18,10 @@ 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 +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> where X: Clone { + | ++++++++++++++ error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:15:33 @@ -43,6 +49,11 @@ 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 +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:26:20 @@ -77,6 +88,11 @@ 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 +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | 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:20 @@ -130,6 +146,11 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); | 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 +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::<i32>()); + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` --> $DIR/invalid-iterator-chain.rs:39:46 @@ -182,6 +203,11 @@ 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 +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | error: aborting due to 7 previous errors |
