Skip to content

Commit c56c7e2

Browse files
committed
Auto merge of rust-lang#5695 - esamudera:lint_mem_uninitialized, r=phansch,oli-obk
New lint: suggest `ptr::read` instead of `mem::replace(..., uninitialized())` resolves: rust-lang#5575 changelog: improvements to `MEM_REPLACE_WITH_UNINIT`: - add a new test case in `tests/ui/repl_uninit.rs` to cover the case of replacing with `mem::MaybeUninit::uninit().assume_init()`. - modify the existing `MEM_REPLACE_WITH_UNINIT` when replacing with `mem::uninitialized` to suggest using `ptr::read` instead. - lint with `MEM_REPLACE_WITH_UNINIT` when replacing with `mem::MaybeUninit::uninit().assume_init()`
2 parents fa0f6a8 + 8c1ee06 commit c56c7e2

File tree

3 files changed

+71
-36
lines changed

3 files changed

+71
-36
lines changed

clippy_lints/src/mem_replace.rs

+54-28
Original file line numberDiff line numberDiff line change
@@ -135,33 +135,59 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest
135135
}
136136
}
137137

138-
fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span: Span) {
139-
if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind {
140-
if_chain! {
141-
if repl_args.is_empty();
142-
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
143-
if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
144-
then {
145-
if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
146-
span_lint_and_help(
147-
cx,
148-
MEM_REPLACE_WITH_UNINIT,
149-
expr_span,
150-
"replacing with `mem::uninitialized()`",
151-
None,
152-
"consider using the `take_mut` crate instead",
153-
);
154-
} else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
155-
!cx.tables.expr_ty(src).is_primitive() {
156-
span_lint_and_help(
157-
cx,
158-
MEM_REPLACE_WITH_UNINIT,
159-
expr_span,
160-
"replacing with `mem::zeroed()`",
161-
None,
162-
"consider using a default value or the `take_mut` crate instead",
163-
);
164-
}
138+
fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
139+
if_chain! {
140+
// check if replacement is mem::MaybeUninit::uninit().assume_init()
141+
if let Some(method_def_id) = cx.tables.type_dependent_def_id(src.hir_id);
142+
if cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id);
143+
then {
144+
let mut applicability = Applicability::MachineApplicable;
145+
span_lint_and_sugg(
146+
cx,
147+
MEM_REPLACE_WITH_UNINIT,
148+
expr_span,
149+
"replacing with `mem::MaybeUninit::uninit().assume_init()`",
150+
"consider using",
151+
format!(
152+
"std::ptr::read({})",
153+
snippet_with_applicability(cx, dest.span, "", &mut applicability)
154+
),
155+
applicability,
156+
);
157+
return;
158+
}
159+
}
160+
161+
if_chain! {
162+
if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind;
163+
if repl_args.is_empty();
164+
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
165+
if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
166+
then {
167+
if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
168+
let mut applicability = Applicability::MachineApplicable;
169+
span_lint_and_sugg(
170+
cx,
171+
MEM_REPLACE_WITH_UNINIT,
172+
expr_span,
173+
"replacing with `mem::uninitialized()`",
174+
"consider using",
175+
format!(
176+
"std::ptr::read({})",
177+
snippet_with_applicability(cx, dest.span, "", &mut applicability)
178+
),
179+
applicability,
180+
);
181+
} else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
182+
!cx.tables.expr_ty(src).is_primitive() {
183+
span_lint_and_help(
184+
cx,
185+
MEM_REPLACE_WITH_UNINIT,
186+
expr_span,
187+
"replacing with `mem::zeroed()`",
188+
None,
189+
"consider using a default value or the `take_mut` crate instead",
190+
);
165191
}
166192
}
167193
}
@@ -209,7 +235,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
209235
if let [dest, src] = &**func_args;
210236
then {
211237
check_replace_option_with_none(cx, src, dest, expr.span);
212-
check_replace_with_uninit(cx, src, expr.span);
238+
check_replace_with_uninit(cx, src, dest, expr.span);
213239
check_replace_with_default(cx, src, dest, expr.span);
214240
}
215241
}

tests/ui/repl_uninit.rs

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ fn main() {
1717
std::mem::forget(mem::replace(&mut v, new_v));
1818
}
1919

20+
unsafe {
21+
let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assume_init());
22+
let new_v = might_panic(taken_v);
23+
std::mem::forget(mem::replace(&mut v, new_v));
24+
}
25+
2026
unsafe {
2127
let taken_v = mem::replace(&mut v, mem::zeroed());
2228
let new_v = might_panic(taken_v);

tests/ui/repl_uninit.stderr

+11-8
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,29 @@ error: replacing with `mem::uninitialized()`
22
--> $DIR/repl_uninit.rs:15:23
33
|
44
LL | let taken_v = mem::replace(&mut v, mem::uninitialized());
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(&mut v)`
66
|
77
= note: `-D clippy::mem-replace-with-uninit` implied by `-D warnings`
8-
= help: consider using the `take_mut` crate instead
98

10-
error: replacing with `mem::zeroed()`
9+
error: replacing with `mem::MaybeUninit::uninit().assume_init()`
1110
--> $DIR/repl_uninit.rs:21:23
1211
|
12+
LL | let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assume_init());
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(&mut v)`
14+
15+
error: replacing with `mem::zeroed()`
16+
--> $DIR/repl_uninit.rs:27:23
17+
|
1318
LL | let taken_v = mem::replace(&mut v, mem::zeroed());
1419
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1520
|
1621
= help: consider using a default value or the `take_mut` crate instead
1722

1823
error: replacing with `mem::uninitialized()`
19-
--> $DIR/repl_uninit.rs:33:28
24+
--> $DIR/repl_uninit.rs:39:28
2025
|
2126
LL | let taken_u = unsafe { mem::replace(uref, mem::uninitialized()) };
22-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23-
|
24-
= help: consider using the `take_mut` crate instead
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(uref)`
2528

26-
error: aborting due to 3 previous errors
29+
error: aborting due to 4 previous errors
2730

0 commit comments

Comments
 (0)