Skip to content

Commit e2dc5a1

Browse files
committed
fix review comments
1 parent c665fb9 commit e2dc5a1

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

clippy_lints/src/needless_move.rs

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,29 @@ declare_clippy_lint! {
5050
/// E.g. all the values are captured by value into the closure / `async` block.
5151
///
5252
/// ### Why is this bad?
53-
/// Pedantry
53+
/// This pattern is not necessarily bad, but sometimes the `move` keyword is unnecessary,
54+
/// for example when there's a closure which captures some variables by reference, so
55+
/// the programmer adds the `move` keyword to move the variables into the closure, but
56+
/// then later decides that he no longer needs the variables in question, so he removes them
57+
/// from the body of the closure, but forgets to also remove the `move` keyword.
58+
///
59+
/// This is really just a strict coding style issue.
60+
///
61+
/// ### Caveats
62+
/// There are some cases where this lint will suggest removing the `move` keyword,
63+
/// but it would be considered idiomatic to keep it.
64+
///
65+
/// For example, the closure passed to `std::thread::spawn` is usually always written
66+
/// with the `move` keyword, even if it's not necessary:
67+
///
68+
/// ```no_run
69+
/// let a = String::new();
70+
/// std::thread::spawn(move || {
71+
/// // ...
72+
/// function_that_does_something_with(a); // a is moved into the closure
73+
/// });
74+
/// ```
75+
///
5476
/// ### Example
5577
/// ```no_run
5678
/// let a = String::new();
@@ -116,31 +138,30 @@ impl NeedlessMove {
116138
}
117139
}
118140

119-
let lint = |note_msg: &'static str| {
120-
span_lint_and_then(
121-
cx,
122-
NEEDLESS_MOVE,
123-
expr.span,
124-
"you seem to use `move`, but the `move` is unnecessary",
125-
|diag| {
126-
diag.suggest_remove_item(cx, move_kw, "remove the `move`", Applicability::MachineApplicable);
127-
diag.note(note_msg);
128-
},
129-
);
130-
};
131-
132-
match lint_result {
141+
let note_msg = match lint_result {
133142
LintResult::NothingCaptured => {
134-
lint("there were no captured variables, so the `move` is unnecessary");
143+
"there were no captured variables, so the `move` is unnecessary"
135144
},
136145
LintResult::Consumed => {
137-
lint("there were consumed variables, but no borrowed variables, so the `move` is unnecessary");
146+
"there were consumed variables, but no borrowed variables, so the `move` is unnecessary"
138147
},
139148
LintResult::NeedMove => {
140149
// there was a value which would be borrowed if it weren't for the move keyword,
141150
// so we should keep it, as removing it would change semantics.
151+
return;
142152
},
143-
}
153+
};
154+
155+
span_lint_and_then(
156+
cx,
157+
NEEDLESS_MOVE,
158+
expr.span,
159+
"you seem to use `move`, but the `move` is unnecessary",
160+
|diag| {
161+
diag.suggest_remove_item(cx, move_kw, "remove the `move`", Applicability::MachineApplicable);
162+
diag.note(note_msg);
163+
},
164+
);
144165
}
145166
}
146167

@@ -150,11 +171,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessMove {
150171
return;
151172
}
152173

153-
let ExprKind::Closure(closure) = &expr.kind else {
154-
return;
155-
};
156-
157-
Self::check_closure(cx, expr, closure);
174+
if let ExprKind::Closure(closure) = &expr.kind {
175+
Self::check_closure(cx, expr, closure);
176+
}
158177
}
159178
}
160179

@@ -175,18 +194,6 @@ struct MovedVariablesCtxt<'tcx> {
175194
}
176195

177196
impl<'tcx> MovedVariablesCtxt<'tcx> {
178-
fn move_common(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, hir_id: HirId) {
179-
if let euv::PlaceBase::Upvar(_) = cmt.place.base {
180-
self.moved.push((cmt.place.clone(), hir_id));
181-
}
182-
}
183-
184-
fn borrow_common(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, borrow_hir_id: HirId, bk: ty::BorrowKind) {
185-
if let euv::PlaceBase::Upvar(_) = cmt.place.base {
186-
self.captured.push((cmt.place.clone(), borrow_hir_id, bk));
187-
}
188-
}
189-
190197
fn get_required_kind(&self, place: &euv::Place<'tcx>, ref_hir_id: HirId) -> UpvarCapture {
191198
if self
192199
.moved
@@ -207,11 +214,15 @@ impl<'tcx> MovedVariablesCtxt<'tcx> {
207214

208215
impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'tcx> {
209216
fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, hir_id: HirId) {
210-
self.move_common(cmt, hir_id);
217+
if let euv::PlaceBase::Upvar(_) = cmt.place.base {
218+
self.moved.push((cmt.place.clone(), hir_id));
219+
}
211220
}
212221

213222
fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, hir_id: HirId, bk: ty::BorrowKind) {
214-
self.borrow_common(cmt, hir_id, bk);
223+
if let euv::PlaceBase::Upvar(_) = cmt.place.base {
224+
self.captured.push((cmt.place.clone(), hir_id, bk));
225+
}
215226
}
216227

217228
fn mutate(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, hir_id: HirId) {

0 commit comments

Comments
 (0)