Skip to content

Commit fb0d7f1

Browse files
committed
Auto merge of #6578 - MarijnS95:size-in-element-count-divide-by-byte-size, r=flip1995
size_of_in_element_count: Disable lint on division by byte-size Fixes #6511 It is fairly common to divide some length in bytes by the byte-size of a single element before creating a `from_raw_parts` slice or similar operation. This lint would erroneously disallow such expressions. Just in case, instead of simply disabling this lint in the RHS of a division, keep track of the inversion and enable it again on recursive division. --- changelog: Do not trigger size_of_in_element_count when dividing by element size
2 parents d71dea4 + d4bf59b commit fb0d7f1

File tree

5 files changed

+103
-66
lines changed

5 files changed

+103
-66
lines changed

clippy_lints/src/size_of_in_element_count.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ declare_clippy_lint! {
3535

3636
declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]);
3737

38-
fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tcx>> {
38+
fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) -> Option<Ty<'tcx>> {
3939
match expr.kind {
4040
ExprKind::Call(count_func, _func_args) => {
4141
if_chain! {
42+
if !inverted;
4243
if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
4344
if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
4445
if match_def_path(cx, def_id, &paths::MEM_SIZE_OF)
@@ -50,10 +51,13 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tc
5051
}
5152
}
5253
},
53-
ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node || BinOpKind::Div == op.node => {
54-
get_size_of_ty(cx, left).or_else(|| get_size_of_ty(cx, right))
54+
ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node => {
55+
get_size_of_ty(cx, left, inverted).or_else(|| get_size_of_ty(cx, right, inverted))
5556
},
56-
ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr),
57+
ExprKind::Binary(op, left, right) if BinOpKind::Div == op.node => {
58+
get_size_of_ty(cx, left, inverted).or_else(|| get_size_of_ty(cx, right, !inverted))
59+
},
60+
ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr, inverted),
5761
_ => None,
5862
}
5963
}
@@ -128,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
128132

129133
// Find a size_of call in the count parameter expression and
130134
// check that it's the same type
131-
if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr);
135+
if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr, false);
132136
if TyS::same_type(pointee_ty, ty_used_for_size_of);
133137
then {
134138
span_lint_and_help(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#![warn(clippy::size_of_in_element_count)]
2+
#![allow(clippy::ptr_offset_with_cast)]
3+
4+
use std::mem::{size_of, size_of_val};
5+
use std::ptr::{copy, copy_nonoverlapping, write_bytes};
6+
7+
fn main() {
8+
const SIZE: usize = 128;
9+
const HALF_SIZE: usize = SIZE / 2;
10+
const DOUBLE_SIZE: usize = SIZE * 2;
11+
let mut x = [2u8; SIZE];
12+
let mut y = [2u8; SIZE];
13+
14+
// Count expression involving multiplication of size_of (Should trigger the lint)
15+
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
16+
17+
// Count expression involving nested multiplications of size_of (Should trigger the lint)
18+
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
19+
20+
// Count expression involving divisions of size_of (Should trigger the lint)
21+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
22+
23+
// Count expression involving divisions by size_of (Should not trigger the lint)
24+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u8>()) };
25+
26+
// Count expression involving divisions by multiple size_of (Should not trigger the lint)
27+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u8>())) };
28+
29+
// Count expression involving recursive divisions by size_of (Should trigger the lint)
30+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
31+
32+
// No size_of calls (Should not trigger the lint)
33+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
34+
35+
// Different types for pointee and size_of (Should not trigger the lint)
36+
unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: found a count of bytes instead of a count of elements of `T`
2+
--> $DIR/expressions.rs:15:62
3+
|
4+
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
8+
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
9+
10+
error: found a count of bytes instead of a count of elements of `T`
11+
--> $DIR/expressions.rs:18:62
12+
|
13+
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
17+
18+
error: found a count of bytes instead of a count of elements of `T`
19+
--> $DIR/expressions.rs:21:47
20+
|
21+
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
25+
26+
error: found a count of bytes instead of a count of elements of `T`
27+
--> $DIR/expressions.rs:30:47
28+
|
29+
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
33+
34+
error: aborting due to 4 previous errors
35+

tests/ui/size_of_in_element_count.rs renamed to tests/ui/size_of_in_element_count/functions.rs

-15
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,4 @@ fn main() {
4343
y.as_mut_ptr().wrapping_add(size_of::<u8>());
4444
unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
4545
y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
46-
47-
// Count expression involving multiplication of size_of (Should trigger the lint)
48-
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
49-
50-
// Count expression involving nested multiplications of size_of (Should trigger the lint)
51-
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
52-
53-
// Count expression involving divisions of size_of (Should trigger the lint)
54-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
55-
56-
// No size_of calls (Should not trigger the lint)
57-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
58-
59-
// Different types for pointee and size_of (Should not trigger the lint)
60-
unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
6146
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: found a count of bytes instead of a count of elements of `T`
2-
--> $DIR/size_of_in_element_count.rs:18:68
2+
--> $DIR/functions.rs:18:68
33
|
44
LL | unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
55
| ^^^^^^^^^^^^^^^
@@ -8,188 +8,164 @@ LL | unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of:
88
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
99

1010
error: found a count of bytes instead of a count of elements of `T`
11-
--> $DIR/size_of_in_element_count.rs:19:62
11+
--> $DIR/functions.rs:19:62
1212
|
1313
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
1414
| ^^^^^^^^^^^^^^^^^^
1515
|
1616
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
1717

1818
error: found a count of bytes instead of a count of elements of `T`
19-
--> $DIR/size_of_in_element_count.rs:21:49
19+
--> $DIR/functions.rs:21:49
2020
|
2121
LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
2222
| ^^^^^^^^^^^^^^^
2323
|
2424
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
2525

2626
error: found a count of bytes instead of a count of elements of `T`
27-
--> $DIR/size_of_in_element_count.rs:22:64
27+
--> $DIR/functions.rs:22:64
2828
|
2929
LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
3030
| ^^^^^^^^^^^^^^^
3131
|
3232
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
3333

3434
error: found a count of bytes instead of a count of elements of `T`
35-
--> $DIR/size_of_in_element_count.rs:23:51
35+
--> $DIR/functions.rs:23:51
3636
|
3737
LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
3838
| ^^^^^^^^^^^^^^^
3939
|
4040
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
4141

4242
error: found a count of bytes instead of a count of elements of `T`
43-
--> $DIR/size_of_in_element_count.rs:24:66
43+
--> $DIR/functions.rs:24:66
4444
|
4545
LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
4646
| ^^^^^^^^^^^^^^^
4747
|
4848
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
4949

5050
error: found a count of bytes instead of a count of elements of `T`
51-
--> $DIR/size_of_in_element_count.rs:26:47
51+
--> $DIR/functions.rs:26:47
5252
|
5353
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
5454
| ^^^^^^^^^^^^^^^
5555
|
5656
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
5757

5858
error: found a count of bytes instead of a count of elements of `T`
59-
--> $DIR/size_of_in_element_count.rs:27:47
59+
--> $DIR/functions.rs:27:47
6060
|
6161
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
6262
| ^^^^^^^^^^^^^^^^^^
6363
|
6464
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
6565

6666
error: found a count of bytes instead of a count of elements of `T`
67-
--> $DIR/size_of_in_element_count.rs:29:46
67+
--> $DIR/functions.rs:29:46
6868
|
6969
LL | unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
7070
| ^^^^^^^^^^^^^^^^^^^^^^
7171
|
7272
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
7373

7474
error: found a count of bytes instead of a count of elements of `T`
75-
--> $DIR/size_of_in_element_count.rs:30:47
75+
--> $DIR/functions.rs:30:47
7676
|
7777
LL | unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
7878
| ^^^^^^^^^^^^^^^^^^^^^^
7979
|
8080
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
8181

8282
error: found a count of bytes instead of a count of elements of `T`
83-
--> $DIR/size_of_in_element_count.rs:32:66
83+
--> $DIR/functions.rs:32:66
8484
|
8585
LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
8686
| ^^^^^^^^^^^^^^^^^^^^^^
8787
|
8888
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
8989

9090
error: found a count of bytes instead of a count of elements of `T`
91-
--> $DIR/size_of_in_element_count.rs:34:46
91+
--> $DIR/functions.rs:34:46
9292
|
9393
LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
9494
| ^^^^^^^^^^^^^^^^^^^^^^
9595
|
9696
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
9797

9898
error: found a count of bytes instead of a count of elements of `T`
99-
--> $DIR/size_of_in_element_count.rs:35:38
99+
--> $DIR/functions.rs:35:38
100100
|
101101
LL | slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
102102
| ^^^^^^^^^^^^^^^^^^^^^^
103103
|
104104
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
105105

106106
error: found a count of bytes instead of a count of elements of `T`
107-
--> $DIR/size_of_in_element_count.rs:37:49
107+
--> $DIR/functions.rs:37:49
108108
|
109109
LL | unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
110110
| ^^^^^^^^^^^^^^^^^^^^^^
111111
|
112112
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
113113

114114
error: found a count of bytes instead of a count of elements of `T`
115-
--> $DIR/size_of_in_element_count.rs:38:41
115+
--> $DIR/functions.rs:38:41
116116
|
117117
LL | unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
118118
| ^^^^^^^^^^^^^^^^^^^^^^
119119
|
120120
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
121121

122122
error: found a count of bytes instead of a count of elements of `T`
123-
--> $DIR/size_of_in_element_count.rs:40:33
123+
--> $DIR/functions.rs:40:33
124124
|
125125
LL | unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
126126
| ^^^^^^^^^^^^^^^
127127
|
128128
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
129129

130130
error: found a count of bytes instead of a count of elements of `T`
131-
--> $DIR/size_of_in_element_count.rs:41:29
131+
--> $DIR/functions.rs:41:29
132132
|
133133
LL | y.as_ptr().wrapping_sub(size_of::<u8>());
134134
| ^^^^^^^^^^^^^^^
135135
|
136136
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
137137

138138
error: found a count of bytes instead of a count of elements of `T`
139-
--> $DIR/size_of_in_element_count.rs:42:29
139+
--> $DIR/functions.rs:42:29
140140
|
141141
LL | unsafe { y.as_ptr().add(size_of::<u8>()) };
142142
| ^^^^^^^^^^^^^^^
143143
|
144144
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
145145

146146
error: found a count of bytes instead of a count of elements of `T`
147-
--> $DIR/size_of_in_element_count.rs:43:33
147+
--> $DIR/functions.rs:43:33
148148
|
149149
LL | y.as_mut_ptr().wrapping_add(size_of::<u8>());
150150
| ^^^^^^^^^^^^^^^
151151
|
152152
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
153153

154154
error: found a count of bytes instead of a count of elements of `T`
155-
--> $DIR/size_of_in_element_count.rs:44:32
155+
--> $DIR/functions.rs:44:32
156156
|
157157
LL | unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
158158
| ^^^^^^^^^^^^^^^^^^^^^^^^
159159
|
160160
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
161161

162162
error: found a count of bytes instead of a count of elements of `T`
163-
--> $DIR/size_of_in_element_count.rs:45:36
163+
--> $DIR/functions.rs:45:36
164164
|
165165
LL | y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
166166
| ^^^^^^^^^^^^^^^^^^^^^^^^
167167
|
168168
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
169169

170-
error: found a count of bytes instead of a count of elements of `T`
171-
--> $DIR/size_of_in_element_count.rs:48:62
172-
|
173-
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
174-
| ^^^^^^^^^^^^^^^^^^^^^^
175-
|
176-
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
177-
178-
error: found a count of bytes instead of a count of elements of `T`
179-
--> $DIR/size_of_in_element_count.rs:51:62
180-
|
181-
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
182-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
183-
|
184-
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
185-
186-
error: found a count of bytes instead of a count of elements of `T`
187-
--> $DIR/size_of_in_element_count.rs:54:47
188-
|
189-
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
190-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
191-
|
192-
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
193-
194-
error: aborting due to 24 previous errors
170+
error: aborting due to 21 previous errors
195171

0 commit comments

Comments
 (0)