Skip to content

Commit 917b538

Browse files
committed
Auto merge of #6962 - TaKO8Ki:fix-false-positive-in-manual-flatten, r=llogiq
Fix false positive in `manual_flatten` This pull request fixes false positive in `manual_flatten` in case using a slice of references . closes: #6893 changelog: fix false positive in `manual_flatten`
2 parents 919a1a4 + 2f8d71b commit 917b538

File tree

4 files changed

+106
-14
lines changed

4 files changed

+106
-14
lines changed

clippy_lints/src/loops/manual_flatten.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use if_chain::if_chain;
66
use rustc_errors::Applicability;
77
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, StmtKind};
88
use rustc_lint::LateContext;
9+
use rustc_middle::ty;
910
use rustc_span::source_map::Span;
1011

1112
/// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
@@ -54,14 +55,21 @@ pub(super) fn check<'tcx>(
5455
// Prepare the help message
5556
let mut applicability = Applicability::MaybeIncorrect;
5657
let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability);
58+
let copied = match cx.typeck_results().expr_ty(match_expr).kind() {
59+
ty::Ref(_, inner, _) => match inner.kind() {
60+
ty::Ref(..) => ".copied()",
61+
_ => ""
62+
}
63+
_ => ""
64+
};
5765

5866
span_lint_and_then(
5967
cx,
6068
MANUAL_FLATTEN,
6169
span,
6270
&msg,
6371
|diag| {
64-
let sugg = format!("{}.flatten()", arg_snippet);
72+
let sugg = format!("{}{}.flatten()", arg_snippet, copied);
6573
diag.span_suggestion(
6674
arg.span,
6775
"try",

clippy_lints/src/methods/utils.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use rustc_ast::ast;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_lint::LateContext;
8-
use rustc_middle::ty;
9-
use rustc_middle::ty::Ty;
8+
use rustc_middle::ty::{self, Ty};
109
use rustc_span::symbol::sym;
1110

1211
pub(super) fn derefs_to_slice<'tcx>(

tests/ui/manual_flatten.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![warn(clippy::manual_flatten)]
2+
#![allow(clippy::useless_vec)]
23

34
fn main() {
45
// Test for loop over implicitly adjusted `Iterator` with `if let` expression
@@ -69,6 +70,27 @@ fn main() {
6970
}
7071
}
7172

73+
let vec_of_ref = vec![&Some(1)];
74+
for n in &vec_of_ref {
75+
if let Some(n) = n {
76+
println!("{:?}", n);
77+
}
78+
}
79+
80+
let vec_of_ref = &vec_of_ref;
81+
for n in vec_of_ref {
82+
if let Some(n) = n {
83+
println!("{:?}", n);
84+
}
85+
}
86+
87+
let slice_of_ref = &[&Some(1)];
88+
for n in slice_of_ref {
89+
if let Some(n) = n {
90+
println!("{:?}", n);
91+
}
92+
}
93+
7294
// Using manual flatten should not trigger the lint
7395
for n in vec![Some(1), Some(2), Some(3)].iter().flatten() {
7496
println!("{}", n);

tests/ui/manual_flatten.stderr

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unnecessary `if let` since only the `Some` variant of the iterator element is used
2-
--> $DIR/manual_flatten.rs:6:5
2+
--> $DIR/manual_flatten.rs:7:5
33
|
44
LL | for n in x {
55
| ^ - help: try: `x.into_iter().flatten()`
@@ -13,15 +13,15 @@ LL | | }
1313
|
1414
= note: `-D clippy::manual-flatten` implied by `-D warnings`
1515
help: ...and remove the `if let` statement in the for loop
16-
--> $DIR/manual_flatten.rs:7:9
16+
--> $DIR/manual_flatten.rs:8:9
1717
|
1818
LL | / if let Some(y) = n {
1919
LL | | println!("{}", y);
2020
LL | | }
2121
| |_________^
2222

2323
error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
24-
--> $DIR/manual_flatten.rs:14:5
24+
--> $DIR/manual_flatten.rs:15:5
2525
|
2626
LL | for n in y.clone() {
2727
| ^ --------- help: try: `y.clone().into_iter().flatten()`
@@ -34,15 +34,15 @@ LL | | }
3434
| |_____^
3535
|
3636
help: ...and remove the `if let` statement in the for loop
37-
--> $DIR/manual_flatten.rs:15:9
37+
--> $DIR/manual_flatten.rs:16:9
3838
|
3939
LL | / if let Ok(n) = n {
4040
LL | | println!("{}", n);
4141
LL | | };
4242
| |_________^
4343

4444
error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
45-
--> $DIR/manual_flatten.rs:21:5
45+
--> $DIR/manual_flatten.rs:22:5
4646
|
4747
LL | for n in &y {
4848
| ^ -- help: try: `y.iter().flatten()`
@@ -55,15 +55,15 @@ LL | | }
5555
| |_____^
5656
|
5757
help: ...and remove the `if let` statement in the for loop
58-
--> $DIR/manual_flatten.rs:22:9
58+
--> $DIR/manual_flatten.rs:23:9
5959
|
6060
LL | / if let Ok(n) = n {
6161
LL | | println!("{}", n);
6262
LL | | }
6363
| |_________^
6464

6565
error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
66-
--> $DIR/manual_flatten.rs:31:5
66+
--> $DIR/manual_flatten.rs:32:5
6767
|
6868
LL | for n in z {
6969
| ^ - help: try: `z.into_iter().flatten()`
@@ -76,15 +76,15 @@ LL | | }
7676
| |_____^
7777
|
7878
help: ...and remove the `if let` statement in the for loop
79-
--> $DIR/manual_flatten.rs:32:9
79+
--> $DIR/manual_flatten.rs:33:9
8080
|
8181
LL | / if let Ok(n) = n {
8282
LL | | println!("{}", n);
8383
LL | | }
8484
| |_________^
8585

8686
error: unnecessary `if let` since only the `Some` variant of the iterator element is used
87-
--> $DIR/manual_flatten.rs:40:5
87+
--> $DIR/manual_flatten.rs:41:5
8888
|
8989
LL | for n in z {
9090
| ^ - help: try: `z.flatten()`
@@ -97,12 +97,75 @@ LL | | }
9797
| |_____^
9898
|
9999
help: ...and remove the `if let` statement in the for loop
100-
--> $DIR/manual_flatten.rs:41:9
100+
--> $DIR/manual_flatten.rs:42:9
101101
|
102102
LL | / if let Some(m) = n {
103103
LL | | println!("{}", m);
104104
LL | | }
105105
| |_________^
106106

107-
error: aborting due to 5 previous errors
107+
error: unnecessary `if let` since only the `Some` variant of the iterator element is used
108+
--> $DIR/manual_flatten.rs:74:5
109+
|
110+
LL | for n in &vec_of_ref {
111+
| ^ ----------- help: try: `vec_of_ref.iter().copied().flatten()`
112+
| _____|
113+
| |
114+
LL | | if let Some(n) = n {
115+
LL | | println!("{:?}", n);
116+
LL | | }
117+
LL | | }
118+
| |_____^
119+
|
120+
help: ...and remove the `if let` statement in the for loop
121+
--> $DIR/manual_flatten.rs:75:9
122+
|
123+
LL | / if let Some(n) = n {
124+
LL | | println!("{:?}", n);
125+
LL | | }
126+
| |_________^
127+
128+
error: unnecessary `if let` since only the `Some` variant of the iterator element is used
129+
--> $DIR/manual_flatten.rs:81:5
130+
|
131+
LL | for n in vec_of_ref {
132+
| ^ ---------- help: try: `vec_of_ref.into_iter().copied().flatten()`
133+
| _____|
134+
| |
135+
LL | | if let Some(n) = n {
136+
LL | | println!("{:?}", n);
137+
LL | | }
138+
LL | | }
139+
| |_____^
140+
|
141+
help: ...and remove the `if let` statement in the for loop
142+
--> $DIR/manual_flatten.rs:82:9
143+
|
144+
LL | / if let Some(n) = n {
145+
LL | | println!("{:?}", n);
146+
LL | | }
147+
| |_________^
148+
149+
error: unnecessary `if let` since only the `Some` variant of the iterator element is used
150+
--> $DIR/manual_flatten.rs:88:5
151+
|
152+
LL | for n in slice_of_ref {
153+
| ^ ------------ help: try: `slice_of_ref.into_iter().copied().flatten()`
154+
| _____|
155+
| |
156+
LL | | if let Some(n) = n {
157+
LL | | println!("{:?}", n);
158+
LL | | }
159+
LL | | }
160+
| |_____^
161+
|
162+
help: ...and remove the `if let` statement in the for loop
163+
--> $DIR/manual_flatten.rs:89:9
164+
|
165+
LL | / if let Some(n) = n {
166+
LL | | println!("{:?}", n);
167+
LL | | }
168+
| |_________^
169+
170+
error: aborting due to 8 previous errors
108171

0 commit comments

Comments
 (0)