Skip to content

Commit f09701a

Browse files
authored
Do not trigger [size_of_in_element_count] for u8 (rust-lang#14011)
Counting in bytes for a pointer to `u8` is legitimate and must not trigger the lint. Also, this prevents linting the `{std,core}::ptr::write_bytes` as it manipulates bytes. Fix rust-lang#6590 changelog: [`size_of_in_element_count`]: do not lint if the pointee type is `u8`
2 parents 390286d + bbd58d1 commit f09701a

File tree

5 files changed

+84
-108
lines changed

5 files changed

+84
-108
lines changed

clippy_lints/src/size_of_in_element_count.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
6363
cx: &LateContext<'tcx>,
6464
expr: &'tcx Expr<'_>,
6565
) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
66-
const METHODS: [&str; 11] = [
67-
"write_bytes",
66+
const METHODS: [&str; 10] = [
6867
"copy_to",
6968
"copy_from",
7069
"copy_to_nonoverlapping",
@@ -79,7 +78,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
7978

8079
if let ExprKind::Call(func, [.., count]) = expr.kind
8180
// Find calls to ptr::{copy, copy_nonoverlapping}
82-
// and ptr::{swap_nonoverlapping, write_bytes},
81+
// and ptr::swap_nonoverlapping,
8382
&& let ExprKind::Path(ref func_qpath) = func.kind
8483
&& let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
8584
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(
@@ -88,7 +87,6 @@ fn get_pointee_ty_and_count_expr<'tcx>(
8887
| sym::ptr_slice_from_raw_parts
8988
| sym::ptr_slice_from_raw_parts_mut
9089
| sym::ptr_swap_nonoverlapping
91-
| sym::ptr_write_bytes
9290
| sym::slice_from_raw_parts
9391
| sym::slice_from_raw_parts_mut
9492
))
@@ -99,7 +97,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
9997
return Some((pointee_ty, count));
10098
}
10199
if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind
102-
// Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
100+
// Find calls to copy_{from,to}{,_nonoverlapping}
103101
&& let method_ident = method_path.ident.as_str()
104102
&& METHODS.iter().any(|m| *m == method_ident)
105103

@@ -121,6 +119,8 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
121119
instead of a count of elements of `T`";
122120

123121
if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr)
122+
// Using a number of bytes for a byte type isn't suspicious
123+
&& pointee_ty != cx.tcx.types.u8
124124
// Find calls to functions with an element count parameter and get
125125
// the pointee type and count parameter expression
126126

tests/ui/size_of_in_element_count/expressions.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,31 @@ fn main() {
88
const SIZE: usize = 128;
99
const HALF_SIZE: usize = SIZE / 2;
1010
const DOUBLE_SIZE: usize = SIZE * 2;
11-
let mut x = [2u8; SIZE];
12-
let mut y = [2u8; SIZE];
11+
let mut x = [2u16; SIZE];
12+
let mut y = [2u16; SIZE];
1313

1414
// 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) };
15+
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>() * SIZE) };
1616
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
1717

1818
// Count expression involving nested multiplications of size_of (Should trigger the lint)
1919
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
2020
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
2121

2222
// Count expression involving divisions of size_of (Should trigger the lint)
23-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
23+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u16>() / 2) };
2424
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
2525

2626
// Count expression involving divisions by size_of (Should not trigger the lint)
27-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u8>()) };
27+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u16>()) };
2828

2929
// Count expression involving divisions by multiple size_of (Should not trigger the lint)
30-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u8>())) };
30+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u16>())) };
3131

3232
// Count expression involving recursive divisions by size_of (Should trigger the lint)
33-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
33+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u16>())) };
3434
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
3535

3636
// No size_of calls (Should not trigger the lint)
3737
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
38-
39-
// Different types for pointee and size_of (Should not trigger the lint)
40-
unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
4138
}

tests/ui/size_of_in_element_count/expressions.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: found a count of bytes instead of a count of elements of `T`
22
--> tests/ui/size_of_in_element_count/expressions.rs:15:62
33
|
4-
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^
4+
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>() * SIZE) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
88
= note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
@@ -19,16 +19,16 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * si
1919
error: found a count of bytes instead of a count of elements of `T`
2020
--> tests/ui/size_of_in_element_count/expressions.rs:23:47
2121
|
22-
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22+
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u16>() / 2) };
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424
|
2525
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
2626

2727
error: found a count of bytes instead of a count of elements of `T`
2828
--> tests/ui/size_of_in_element_count/expressions.rs:33:47
2929
|
30-
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u16>())) };
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3232
|
3333
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
3434

tests/ui/size_of_in_element_count/functions.rs

+19-24
Original file line numberDiff line numberDiff line change
@@ -11,57 +11,52 @@ fn main() {
1111
const SIZE: usize = 128;
1212
const HALF_SIZE: usize = SIZE / 2;
1313
const DOUBLE_SIZE: usize = SIZE * 2;
14-
let mut x = [2u8; SIZE];
15-
let mut y = [2u8; SIZE];
14+
let mut x = [2u16; SIZE];
15+
let mut y = [2u16; SIZE];
1616

1717
// Count is size_of (Should trigger the lint)
18-
unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
18+
unsafe { copy_nonoverlapping::<u16>(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
1919
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
2020
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
2121
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
2222

23-
unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
23+
unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u16>()) };
2424
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
25-
unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
25+
unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u16>()) };
2626
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
27-
unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
27+
unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u16>()) };
2828
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
29-
unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
29+
unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u16>()) };
3030
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
3131

32-
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
32+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
3333
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
3434
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
3535
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
3636

37-
unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
38-
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
39-
unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
40-
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
41-
42-
unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
37+
unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u16>() * SIZE) };
4338
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
4439

45-
slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
40+
slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE);
4641
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
47-
slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
42+
slice_from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE);
4843
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
4944

50-
unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
45+
unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE) };
5146
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
52-
unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
47+
unsafe { from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE) };
5348
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
5449

55-
unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
50+
unsafe { y.as_mut_ptr().sub(size_of::<u16>()) };
5651
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
57-
y.as_ptr().wrapping_sub(size_of::<u8>());
52+
y.as_ptr().wrapping_sub(size_of::<u16>());
5853
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
59-
unsafe { y.as_ptr().add(size_of::<u8>()) };
54+
unsafe { y.as_ptr().add(size_of::<u16>()) };
6055
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
61-
y.as_mut_ptr().wrapping_add(size_of::<u8>());
56+
y.as_mut_ptr().wrapping_add(size_of::<u16>());
6257
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
63-
unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
58+
unsafe { y.as_ptr().offset(size_of::<u16>() as isize) };
6459
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
65-
y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
60+
y.as_mut_ptr().wrapping_offset(size_of::<u16>() as isize);
6661
//~^ ERROR: found a count of bytes instead of a count of elements of `T`
6762
}

0 commit comments

Comments
 (0)