Skip to content

Commit 33c8bc2

Browse files
committed
size_of_in_element_count: Disable lint on division by byte-size
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.
1 parent 6be5a9d commit 33c8bc2

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
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(

tests/ui/size_of_in_element_count/expressions.rs

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ fn main() {
2222
// Count expression involving divisions of size_of (Should trigger the lint)
2323
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
2424

25+
// Count expression involving divisions by size_of (Should not trigger the lint)
26+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u8>()) };
27+
28+
// Count expression involving divisions by multiple size_of (Should not trigger the lint)
29+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u8>())) };
30+
31+
// Count expression involving recursive divisions by size_of (Should trigger the lint)
32+
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
33+
2534
// No size_of calls (Should not trigger the lint)
2635
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
2736

tests/ui/size_of_in_element_count/expressions.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,13 @@ LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>()
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

26-
error: aborting due to 3 previous errors
26+
error: found a count of bytes instead of a count of elements of `T`
27+
--> $DIR/expressions.rs:32: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
2735

0 commit comments

Comments
 (0)