Skip to content

Commit e9440cb

Browse files
committed
Auto merge of #5997 - giraffate:fix_fp_about_clone_in_same_item_push, r=ebroto
Fix FP in `same_item_push` Don't emit a lint when the pushed item doesn't have Clone trait Fix #5979 changelog: Fix FP in `same_item_push` not to emit a lint when the pushed item doesn't have Clone trait
2 parents 3cecdc9 + 96b31a5 commit e9440cb

File tree

2 files changed

+61
-35
lines changed

2 files changed

+61
-35
lines changed

clippy_lints/src/loops.rs

+44-35
Original file line numberDiff line numberDiff line change
@@ -1140,43 +1140,52 @@ fn detect_same_item_push<'tcx>(
11401140
walk_expr(&mut same_item_push_visitor, body);
11411141
if same_item_push_visitor.should_lint {
11421142
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 let PatKind::Wild = pat.kind {
1145-
let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
1146-
let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
1147-
if let ExprKind::Path(ref qpath) = pushed_item.kind {
1148-
if_chain! {
1149-
if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id);
1150-
let node = cx.tcx.hir().get(hir_id);
1151-
if let Node::Binding(pat) = node;
1152-
if let PatKind::Binding(bind_ann, ..) = pat.kind;
1153-
if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
1154-
then {
1155-
span_lint_and_help(
1156-
cx,
1157-
SAME_ITEM_PUSH,
1158-
vec.span,
1159-
"it looks like the same item is being pushed into this Vec",
1160-
None,
1161-
&format!(
1162-
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1163-
item_str, vec_str, item_str
1164-
),
1165-
)
1143+
let vec_ty = cx.typeck_results().expr_ty(vec);
1144+
let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
1145+
if cx
1146+
.tcx
1147+
.lang_items()
1148+
.clone_trait()
1149+
.map_or(false, |id| implements_trait(cx, ty, id, &[]))
1150+
{
1151+
// Make sure that the push does not involve possibly mutating values
1152+
if let PatKind::Wild = pat.kind {
1153+
let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
1154+
let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
1155+
if let ExprKind::Path(ref qpath) = pushed_item.kind {
1156+
if_chain! {
1157+
if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id);
1158+
let node = cx.tcx.hir().get(hir_id);
1159+
if let Node::Binding(pat) = node;
1160+
if let PatKind::Binding(bind_ann, ..) = pat.kind;
1161+
if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
1162+
then {
1163+
span_lint_and_help(
1164+
cx,
1165+
SAME_ITEM_PUSH,
1166+
vec.span,
1167+
"it looks like the same item is being pushed into this Vec",
1168+
None,
1169+
&format!(
1170+
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1171+
item_str, vec_str, item_str
1172+
),
1173+
)
1174+
}
11661175
}
1176+
} else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) {
1177+
span_lint_and_help(
1178+
cx,
1179+
SAME_ITEM_PUSH,
1180+
vec.span,
1181+
"it looks like the same item is being pushed into this Vec",
1182+
None,
1183+
&format!(
1184+
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1185+
item_str, vec_str, item_str
1186+
),
1187+
)
11671188
}
1168-
} else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) {
1169-
span_lint_and_help(
1170-
cx,
1171-
SAME_ITEM_PUSH,
1172-
vec.span,
1173-
"it looks like the same item is being pushed into this Vec",
1174-
None,
1175-
&format!(
1176-
"try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
1177-
item_str, vec_str, item_str
1178-
),
1179-
)
11801189
}
11811190
}
11821191
}

tests/ui/same_item_push.rs

+17
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,21 @@ fn main() {
9494
vec13.push(item);
9595
item += 10;
9696
}
97+
98+
// Fix #5979
99+
let mut vec14: Vec<std::fs::File> = Vec::new();
100+
for _ in 0..10 {
101+
vec14.push(std::fs::File::open("foobar").unwrap());
102+
}
103+
// Fix #5979
104+
#[derive(Clone)]
105+
struct S {}
106+
107+
trait T {}
108+
impl T for S {}
109+
110+
let mut vec15: Vec<Box<dyn T>> = Vec::new();
111+
for _ in 0..10 {
112+
vec15.push(Box::new(S {}));
113+
}
97114
}

0 commit comments

Comments
 (0)