Skip to content

Commit 2800251

Browse files
committed
Auto merge of rust-lang#12742 - Alexendoo:assigning-clones-nested-late-init, r=dswij
Don't lint assigning_clones on nested late init locals Fixes rust-lang#12741 changelog: none
2 parents 993d8ae + c313ef5 commit 2800251

File tree

5 files changed

+39
-14
lines changed

5 files changed

+39
-14
lines changed

clippy_lints/src/assigning_clones.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use clippy_config::msrvs::{self, Msrv};
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::macros::HirNode;
44
use clippy_utils::sugg::Sugg;
5-
use clippy_utils::{is_trait_method, path_to_local};
5+
use clippy_utils::{is_trait_method, local_is_initialized, path_to_local};
66
use rustc_errors::Applicability;
7-
use rustc_hir::{self as hir, Expr, ExprKind, Node};
7+
use rustc_hir::{self as hir, Expr, ExprKind};
88
use rustc_lint::{LateContext, LateLintPass};
99
use rustc_middle::ty::{self, Instance, Mutability};
1010
use rustc_session::impl_lint_pass;
@@ -164,9 +164,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
164164
// TODO: This check currently bails if the local variable has no initializer.
165165
// That is overly conservative - the lint should fire even if there was no initializer,
166166
// but the variable has been initialized before `lhs` was evaluated.
167-
if let Some(Node::LetStmt(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p))
168-
&& local.init.is_none()
169-
{
167+
if !local_is_initialized(cx, local) {
170168
return false;
171169
}
172170
}

clippy_utils/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,21 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
192192
None
193193
}
194194

195+
/// Checks if the given local has an initializer or is from something other than a `let` statement
196+
///
197+
/// e.g. returns true for `x` in `fn f(x: usize) { .. }` and `let x = 1;` but false for `let x;`
198+
pub fn local_is_initialized(cx: &LateContext<'_>, local: HirId) -> bool {
199+
for (_, node) in cx.tcx.hir().parent_iter(local) {
200+
match node {
201+
Node::Pat(..) | Node::PatField(..) => {},
202+
Node::LetStmt(let_stmt) => return let_stmt.init.is_some(),
203+
_ => return true,
204+
}
205+
}
206+
207+
false
208+
}
209+
195210
/// Returns `true` if the given `NodeId` is inside a constant context
196211
///
197212
/// # Example

tests/ui/assigning_clones.fixed

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) {
8686
a = b.clone();
8787
}
8888

89+
fn late_init_let_tuple() {
90+
let (p, q): (String, String);
91+
p = "ghi".to_string();
92+
q = p.clone();
93+
}
94+
8995
#[derive(Clone)]
9096
pub struct HasDeriveClone;
9197

tests/ui/assigning_clones.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) {
8686
a = b.clone();
8787
}
8888

89+
fn late_init_let_tuple() {
90+
let (p, q): (String, String);
91+
p = "ghi".to_string();
92+
q = p.clone();
93+
}
94+
8995
#[derive(Clone)]
9096
pub struct HasDeriveClone;
9197

tests/ui/assigning_clones.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,55 +68,55 @@ LL | a = b.clone();
6868
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
6969

7070
error: assigning the result of `Clone::clone()` may be inefficient
71-
--> tests/ui/assigning_clones.rs:133:5
71+
--> tests/ui/assigning_clones.rs:139:5
7272
|
7373
LL | a = b.clone();
7474
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
7575

7676
error: assigning the result of `Clone::clone()` may be inefficient
77-
--> tests/ui/assigning_clones.rs:140:5
77+
--> tests/ui/assigning_clones.rs:146:5
7878
|
7979
LL | a = b.clone();
8080
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
8181

8282
error: assigning the result of `ToOwned::to_owned()` may be inefficient
83-
--> tests/ui/assigning_clones.rs:141:5
83+
--> tests/ui/assigning_clones.rs:147:5
8484
|
8585
LL | a = c.to_owned();
8686
| ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)`
8787

8888
error: assigning the result of `ToOwned::to_owned()` may be inefficient
89-
--> tests/ui/assigning_clones.rs:171:5
89+
--> tests/ui/assigning_clones.rs:177:5
9090
|
9191
LL | *mut_string = ref_str.to_owned();
9292
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
9393

9494
error: assigning the result of `ToOwned::to_owned()` may be inefficient
95-
--> tests/ui/assigning_clones.rs:175:5
95+
--> tests/ui/assigning_clones.rs:181:5
9696
|
9797
LL | mut_string = ref_str.to_owned();
9898
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
9999

100100
error: assigning the result of `ToOwned::to_owned()` may be inefficient
101-
--> tests/ui/assigning_clones.rs:196:5
101+
--> tests/ui/assigning_clones.rs:202:5
102102
|
103103
LL | **mut_box_string = ref_str.to_owned();
104104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
105105

106106
error: assigning the result of `ToOwned::to_owned()` may be inefficient
107-
--> tests/ui/assigning_clones.rs:200:5
107+
--> tests/ui/assigning_clones.rs:206:5
108108
|
109109
LL | **mut_box_string = ref_str.to_owned();
110110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
111111

112112
error: assigning the result of `ToOwned::to_owned()` may be inefficient
113-
--> tests/ui/assigning_clones.rs:204:5
113+
--> tests/ui/assigning_clones.rs:210:5
114114
|
115115
LL | *mut_thing = ToOwned::to_owned(ref_str);
116116
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
117117

118118
error: assigning the result of `ToOwned::to_owned()` may be inefficient
119-
--> tests/ui/assigning_clones.rs:208:5
119+
--> tests/ui/assigning_clones.rs:214:5
120120
|
121121
LL | mut_thing = ToOwned::to_owned(ref_str);
122122
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`

0 commit comments

Comments
 (0)