Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e28d2bd

Browse files
committedOct 1, 2020
Auto merge of rust-lang#77403 - flip1995:beta, r=pietroalbini
[beta][clippy] backport multiple FP fixes for a warn-by-default lint This backports the PR rust-lang/rust-clippy#6016 fixing multiple FPs: rust-lang/rust-clippy#5902 rust-lang/rust-clippy#5979 rust-lang/rust-clippy#5985 We didn't have any complaints about this lint, since me merged this PR. cc `@ebroto` (sorry I forgot about this, since we talked about the backport 3 weeks ago 😐) r? `@pietroalbini`
2 parents 9f0e6fa + 4a91098 commit e28d2bd

File tree

3 files changed

+179
-61
lines changed

3 files changed

+179
-61
lines changed
 

‎src/tools/clippy/clippy_lints/src/loops.rs

+65-17
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,27 @@ fn detect_same_item_push<'tcx>(
11311131
body: &'tcx Expr<'_>,
11321132
_: &'tcx Expr<'_>,
11331133
) {
1134+
fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>) {
1135+
let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
1136+
let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
1137+
1138+
span_lint_and_help(
1139+
cx,
1140+
SAME_ITEM_PUSH,
1141+
vec.span,
1142+
"it looks like the same item is being pushed into this Vec",
1143+
None,
1144+
&format!(
1145+
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1146+
item_str, vec_str, item_str
1147+
),
1148+
)
1149+
}
1150+
1151+
if !matches!(pat.kind, PatKind::Wild) {
1152+
return;
1153+
}
1154+
11341155
// Determine whether it is safe to lint the body
11351156
let mut same_item_push_visitor = SameItemPushVisitor {
11361157
should_lint: true,
@@ -1140,23 +1161,50 @@ fn detect_same_item_push<'tcx>(
11401161
walk_expr(&mut same_item_push_visitor, body);
11411162
if same_item_push_visitor.should_lint {
11421163
if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push {
1143-
// Make sure that the push does not involve possibly mutating values
1144-
if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) {
1145-
if let PatKind::Wild = pat.kind {
1146-
let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
1147-
let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
1148-
1149-
span_lint_and_help(
1150-
cx,
1151-
SAME_ITEM_PUSH,
1152-
vec.span,
1153-
"it looks like the same item is being pushed into this Vec",
1154-
None,
1155-
&format!(
1156-
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1157-
item_str, vec_str, item_str
1158-
),
1159-
)
1164+
let vec_ty = cx.typeck_results().expr_ty(vec);
1165+
let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
1166+
if cx
1167+
.tcx
1168+
.lang_items()
1169+
.clone_trait()
1170+
.map_or(false, |id| implements_trait(cx, ty, id, &[]))
1171+
{
1172+
// Make sure that the push does not involve possibly mutating values
1173+
match pushed_item.kind {
1174+
ExprKind::Path(ref qpath) => {
1175+
match qpath_res(cx, qpath, pushed_item.hir_id) {
1176+
// immutable bindings that are initialized with literal or constant
1177+
Res::Local(hir_id) => {
1178+
if_chain! {
1179+
let node = cx.tcx.hir().get(hir_id);
1180+
if let Node::Binding(pat) = node;
1181+
if let PatKind::Binding(bind_ann, ..) = pat.kind;
1182+
if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
1183+
let parent_node = cx.tcx.hir().get_parent_node(hir_id);
1184+
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
1185+
if let Some(init) = parent_let_expr.init;
1186+
then {
1187+
match init.kind {
1188+
// immutable bindings that are initialized with literal
1189+
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
1190+
// immutable bindings that are initialized with constant
1191+
ExprKind::Path(ref path) => {
1192+
if let Res::Def(DefKind::Const, ..) = qpath_res(cx, path, init.hir_id) {
1193+
emit_lint(cx, vec, pushed_item);
1194+
}
1195+
}
1196+
_ => {},
1197+
}
1198+
}
1199+
}
1200+
},
1201+
// constant
1202+
Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item),
1203+
_ => {},
1204+
}
1205+
},
1206+
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
1207+
_ => {},
11601208
}
11611209
}
11621210
}
+89-27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![warn(clippy::same_item_push)]
22

3+
const VALUE: u8 = 7;
4+
35
fn mutate_increment(x: &mut u8) -> u8 {
46
*x += 1;
57
*x
@@ -9,65 +11,81 @@ fn increment(x: u8) -> u8 {
911
x + 1
1012
}
1113

12-
fn main() {
13-
// Test for basic case
14-
let mut spaces = Vec::with_capacity(10);
15-
for _ in 0..10 {
16-
spaces.push(vec![b' ']);
17-
}
14+
fn fun() -> usize {
15+
42
16+
}
1817

19-
let mut vec2: Vec<u8> = Vec::new();
18+
fn main() {
19+
// ** linted cases **
20+
let mut vec: Vec<u8> = Vec::new();
2021
let item = 2;
2122
for _ in 5..=20 {
22-
vec2.push(item);
23+
vec.push(item);
2324
}
2425

25-
let mut vec3: Vec<u8> = Vec::new();
26+
let mut vec: Vec<u8> = Vec::new();
2627
for _ in 0..15 {
2728
let item = 2;
28-
vec3.push(item);
29+
vec.push(item);
2930
}
3031

31-
let mut vec4: Vec<u8> = Vec::new();
32+
let mut vec: Vec<u8> = Vec::new();
3233
for _ in 0..15 {
33-
vec4.push(13);
34+
vec.push(13);
35+
}
36+
37+
let mut vec = Vec::new();
38+
for _ in 0..20 {
39+
vec.push(VALUE);
40+
}
41+
42+
let mut vec = Vec::new();
43+
let item = VALUE;
44+
for _ in 0..20 {
45+
vec.push(item);
46+
}
47+
48+
// ** non-linted cases **
49+
let mut spaces = Vec::with_capacity(10);
50+
for _ in 0..10 {
51+
spaces.push(vec![b' ']);
3452
}
3553

3654
// Suggestion should not be given as pushed variable can mutate
37-
let mut vec5: Vec<u8> = Vec::new();
55+
let mut vec: Vec<u8> = Vec::new();
3856
let mut item: u8 = 2;
3957
for _ in 0..30 {
40-
vec5.push(mutate_increment(&mut item));
58+
vec.push(mutate_increment(&mut item));
4159
}
4260

43-
let mut vec6: Vec<u8> = Vec::new();
61+
let mut vec: Vec<u8> = Vec::new();
4462
let mut item: u8 = 2;
4563
let mut item2 = &mut mutate_increment(&mut item);
4664
for _ in 0..30 {
47-
vec6.push(mutate_increment(item2));
65+
vec.push(mutate_increment(item2));
4866
}
4967

50-
let mut vec7: Vec<usize> = Vec::new();
68+
let mut vec: Vec<usize> = Vec::new();
5169
for (a, b) in [0, 1, 4, 9, 16].iter().enumerate() {
52-
vec7.push(a);
70+
vec.push(a);
5371
}
5472

55-
let mut vec8: Vec<u8> = Vec::new();
73+
let mut vec: Vec<u8> = Vec::new();
5674
for i in 0..30 {
57-
vec8.push(increment(i));
75+
vec.push(increment(i));
5876
}
5977

60-
let mut vec9: Vec<u8> = Vec::new();
78+
let mut vec: Vec<u8> = Vec::new();
6179
for i in 0..30 {
62-
vec9.push(i + i * i);
80+
vec.push(i + i * i);
6381
}
6482

6583
// Suggestion should not be given as there are multiple pushes that are not the same
66-
let mut vec10: Vec<u8> = Vec::new();
84+
let mut vec: Vec<u8> = Vec::new();
6785
let item: u8 = 2;
6886
for _ in 0..30 {
69-
vec10.push(item);
70-
vec10.push(item * 2);
87+
vec.push(item);
88+
vec.push(item * 2);
7189
}
7290

7391
// Suggestion should not be given as Vec is not involved
@@ -82,8 +100,52 @@ fn main() {
82100
for i in 0..30 {
83101
vec_a.push(A { kind: i });
84102
}
85-
let mut vec12: Vec<u8> = Vec::new();
103+
let mut vec: Vec<u8> = Vec::new();
86104
for a in vec_a {
87-
vec12.push(2u8.pow(a.kind));
105+
vec.push(2u8.pow(a.kind));
106+
}
107+
108+
// Fix #5902
109+
let mut vec: Vec<u8> = Vec::new();
110+
let mut item = 0;
111+
for _ in 0..10 {
112+
vec.push(item);
113+
item += 10;
114+
}
115+
116+
// Fix #5979
117+
let mut vec: Vec<std::fs::File> = Vec::new();
118+
for _ in 0..10 {
119+
vec.push(std::fs::File::open("foobar").unwrap());
120+
}
121+
// Fix #5979
122+
#[derive(Clone)]
123+
struct S {}
124+
125+
trait T {}
126+
impl T for S {}
127+
128+
let mut vec: Vec<Box<dyn T>> = Vec::new();
129+
for _ in 0..10 {
130+
vec.push(Box::new(S {}));
131+
}
132+
133+
// Fix #5985
134+
let mut vec = Vec::new();
135+
let item = 42;
136+
let item = fun();
137+
for _ in 0..20 {
138+
vec.push(item);
139+
}
140+
141+
// Fix #5985
142+
let mut vec = Vec::new();
143+
let key = 1;
144+
for _ in 0..20 {
145+
let item = match key {
146+
1 => 10,
147+
_ => 0,
148+
};
149+
vec.push(item);
88150
}
89151
}
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
error: it looks like the same item is being pushed into this Vec
2-
--> $DIR/same_item_push.rs:16:9
2+
--> $DIR/same_item_push.rs:23:9
33
|
4-
LL | spaces.push(vec![b' ']);
5-
| ^^^^^^
4+
LL | vec.push(item);
5+
| ^^^
66
|
77
= note: `-D clippy::same-item-push` implied by `-D warnings`
8-
= help: try using vec![vec![b' '];SIZE] or spaces.resize(NEW_SIZE, vec![b' '])
8+
= help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
99

1010
error: it looks like the same item is being pushed into this Vec
11-
--> $DIR/same_item_push.rs:22:9
11+
--> $DIR/same_item_push.rs:29:9
1212
|
13-
LL | vec2.push(item);
14-
| ^^^^
13+
LL | vec.push(item);
14+
| ^^^
1515
|
16-
= help: try using vec![item;SIZE] or vec2.resize(NEW_SIZE, item)
16+
= help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
1717

1818
error: it looks like the same item is being pushed into this Vec
19-
--> $DIR/same_item_push.rs:28:9
19+
--> $DIR/same_item_push.rs:34:9
2020
|
21-
LL | vec3.push(item);
22-
| ^^^^
21+
LL | vec.push(13);
22+
| ^^^
2323
|
24-
= help: try using vec![item;SIZE] or vec3.resize(NEW_SIZE, item)
24+
= help: try using vec![13;SIZE] or vec.resize(NEW_SIZE, 13)
2525

2626
error: it looks like the same item is being pushed into this Vec
27-
--> $DIR/same_item_push.rs:33:9
27+
--> $DIR/same_item_push.rs:39:9
2828
|
29-
LL | vec4.push(13);
30-
| ^^^^
29+
LL | vec.push(VALUE);
30+
| ^^^
3131
|
32-
= help: try using vec![13;SIZE] or vec4.resize(NEW_SIZE, 13)
32+
= help: try using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE)
3333

34-
error: aborting due to 4 previous errors
34+
error: it looks like the same item is being pushed into this Vec
35+
--> $DIR/same_item_push.rs:45:9
36+
|
37+
LL | vec.push(item);
38+
| ^^^
39+
|
40+
= help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
41+
42+
error: aborting due to 5 previous errors
3543

0 commit comments

Comments
 (0)
Please sign in to comment.