Skip to content

Commit 89124a0

Browse files
committed
Do not use DerefMut on ManuallyDrop<_> union fields
1 parent 1c44c8d commit 89124a0

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

clippy_lints/src/reference.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
3+
use clippy_utils::ty::adjust_derefs_manually_drop;
34
use rustc_errors::Applicability;
4-
use rustc_hir::{Expr, ExprKind, Mutability, UnOp};
5+
use rustc_hir::{Expr, ExprKind, Mutability, Node, UnOp};
56
use rustc_lint::{LateContext, LateLintPass};
67
use rustc_session::declare_lint_pass;
78
use rustc_span::{BytePos, Span};
@@ -44,6 +45,7 @@ impl LateLintPass<'_> for DerefAddrOf {
4445
// NOTE(tesuji): `*&` forces rustc to const-promote the array to `.rodata` section.
4546
// See #12854 for details.
4647
&& !matches!(addrof_target.kind, ExprKind::Array(_))
48+
&& !is_manually_drop_union_field(cx, addrof_target)
4749
&& deref_target.span.eq_ctxt(e.span)
4850
&& !addrof_target.span.from_expansion()
4951
{
@@ -102,3 +104,23 @@ impl LateLintPass<'_> for DerefAddrOf {
102104
}
103105
}
104106
}
107+
108+
/// Check if `expr` is an access to an union field which contains a dereferenced
109+
/// `ManuallyDrop<_>` entity.
110+
fn is_manually_drop_union_field(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
111+
let typeck = cx.typeck_results();
112+
if let ExprKind::Field(parent, _) = expr.kind
113+
&& typeck.expr_ty_adjusted(parent).is_union()
114+
{
115+
for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) {
116+
if let Node::Expr(expr) = node {
117+
if adjust_derefs_manually_drop(typeck.expr_adjustments(expr), typeck.expr_ty(expr)) {
118+
return true;
119+
}
120+
} else {
121+
break;
122+
}
123+
}
124+
}
125+
false
126+
}

tests/ui/deref_addrof.fixed

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@aux-build:proc_macros.rs
22

3-
#![allow(clippy::return_self_not_must_use, clippy::useless_vec)]
3+
#![allow(dangerous_implicit_autorefs, clippy::return_self_not_must_use, clippy::useless_vec)]
44
#![warn(clippy::deref_addrof)]
55

66
extern crate proc_macros;
@@ -72,3 +72,34 @@ impl S {
7272
//~^ deref_addrof
7373
}
7474
}
75+
76+
fn issue14386() {
77+
use std::mem::ManuallyDrop;
78+
79+
#[derive(Copy, Clone)]
80+
struct Data {
81+
num: u64,
82+
}
83+
84+
union DataWithPadding {
85+
data: ManuallyDrop<Data>,
86+
prim: ManuallyDrop<u64>,
87+
padding: [u8; size_of::<Data>()],
88+
tup: (ManuallyDrop<Data>, ()),
89+
}
90+
91+
let mut a = DataWithPadding {
92+
padding: [0; size_of::<DataWithPadding>()],
93+
};
94+
unsafe {
95+
a.padding = [1; size_of::<DataWithPadding>()];
96+
//~^ deref_addrof
97+
a.tup.1 = ();
98+
//~^ deref_addrof
99+
*a.prim = 0;
100+
//~^ deref_addrof
101+
102+
(*(&raw mut a.data)).num = 42;
103+
(*(&raw mut a.tup)).0.num = 42;
104+
}
105+
}

tests/ui/deref_addrof.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@aux-build:proc_macros.rs
22

3-
#![allow(clippy::return_self_not_must_use, clippy::useless_vec)]
3+
#![allow(dangerous_implicit_autorefs, clippy::return_self_not_must_use, clippy::useless_vec)]
44
#![warn(clippy::deref_addrof)]
55

66
extern crate proc_macros;
@@ -72,3 +72,34 @@ impl S {
7272
//~^ deref_addrof
7373
}
7474
}
75+
76+
fn issue14386() {
77+
use std::mem::ManuallyDrop;
78+
79+
#[derive(Copy, Clone)]
80+
struct Data {
81+
num: u64,
82+
}
83+
84+
union DataWithPadding {
85+
data: ManuallyDrop<Data>,
86+
prim: ManuallyDrop<u64>,
87+
padding: [u8; size_of::<Data>()],
88+
tup: (ManuallyDrop<Data>, ()),
89+
}
90+
91+
let mut a = DataWithPadding {
92+
padding: [0; size_of::<DataWithPadding>()],
93+
};
94+
unsafe {
95+
(*(&raw mut a.padding)) = [1; size_of::<DataWithPadding>()];
96+
//~^ deref_addrof
97+
(*(&raw mut a.tup)).1 = ();
98+
//~^ deref_addrof
99+
*(*(&raw mut a.prim)) = 0;
100+
//~^ deref_addrof
101+
102+
(*(&raw mut a.data)).num = 42;
103+
(*(&raw mut a.tup)).0.num = 42;
104+
}
105+
}

tests/ui/deref_addrof.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,23 @@ LL | inline!(*&mut $(@expr self))
7171
|
7272
= note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
7373

74-
error: aborting due to 11 previous errors
74+
error: immediately dereferencing a reference
75+
--> tests/ui/deref_addrof.rs:95:9
76+
|
77+
LL | (*(&raw mut a.padding)) = [1; size_of::<DataWithPadding>()];
78+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.padding`
79+
80+
error: immediately dereferencing a reference
81+
--> tests/ui/deref_addrof.rs:97:9
82+
|
83+
LL | (*(&raw mut a.tup)).1 = ();
84+
| ^^^^^^^^^^^^^^^^^^^ help: try: `a.tup`
85+
86+
error: immediately dereferencing a reference
87+
--> tests/ui/deref_addrof.rs:99:10
88+
|
89+
LL | *(*(&raw mut a.prim)) = 0;
90+
| ^^^^^^^^^^^^^^^^^^^^ help: try: `a.prim`
91+
92+
error: aborting due to 14 previous errors
7593

0 commit comments

Comments
 (0)