forked from rust-lang/rust-clippy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathraw_assign_to_drop.rs
More file actions
43 lines (41 loc) · 1.72 KB
/
Copy pathraw_assign_to_drop.rs
File metadata and controls
43 lines (41 loc) · 1.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::LateContext;
use super::RAW_ASSIGN_TO_DROP;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, lhs: &'tcx Expr<'_>) {
if let ExprKind::Unary(UnOp::Deref, expr) = lhs.kind
&& let ty = cx.typeck_results().expr_ty(expr)
&& ty.is_raw_ptr()
&& let Some(deref_ty) = ty.builtin_deref(true)
&& deref_ty.needs_drop(cx.tcx, cx.typing_env())
{
if let ExprKind::MethodCall(path, self_arg, [], ..) = expr.kind
&& let rustc_middle::ty::Adt(ty_def, ..) = cx.typeck_results().expr_ty(self_arg).kind()
&& ty_def.is_unsafe_cell()
&& path.ident.as_str() == "get"
{
// Don't lint if the raw pointer was directly retrieved from UnsafeCell::get()
// We assume those to be safely managed
return;
}
span_lint_and_then(
cx,
RAW_ASSIGN_TO_DROP,
expr.span,
"assignment via raw pointer always executes destructor",
|diag| {
diag.note(format!(
"the destructor defined by `{deref_ty}` is executed during assignment of the new value"
));
diag.span_label(
expr.span,
"the old value may be uninitialized, causing Undefined Behavior when the destructor executes",
);
diag.help("use `std::ptr::write()` to overwrite a possibly uninitialized place");
diag.help(
"use `std::ptr::drop_in_place()` to drop the previous value, having established such value exists",
);
},
);
}
}