Skip to content

Commit a6c2c18

Browse files
Extend zst_offset lint to detect NonNull<T> offset calculations (#16888)
Fixes #16887 The `zst_offset` lint previously only checked raw pointers (`*mut T` / `*const T`) for offset calculations on zero-sized types. `NonNull<T>` also provides `add`, `sub`, and `offset` methods that are equally no-ops on ZSTs, but were not flagged. The PR extends the lint to also check `NonNull<T>` receivers. changelog: [`zst_offset`]: detect zero-sized `NonNull<T>` offset calculations.
2 parents f058fe7 + d41c959 commit a6c2c18

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

clippy_lints/src/methods/zst_offset.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::res::MaybeDef;
23
use rustc_hir as hir;
34
use rustc_lint::LateContext;
45
use rustc_middle::ty;
6+
use rustc_span::sym;
57

68
use super::ZST_OFFSET;
79

810
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
9-
if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind()
10-
&& let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty))
11+
let recv_ty = cx.typeck_results().expr_ty(recv);
12+
let pointee_ty = match recv_ty.kind() {
13+
ty::RawPtr(ty, _) => *ty,
14+
ty::Adt(_, args) if recv_ty.is_diag_item(cx, sym::NonNull) => args.type_at(0),
15+
_ => return,
16+
};
17+
if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(pointee_ty))
1118
&& layout.is_zst()
1219
{
1320
span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");

tests/ui/zero_offset.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,18 @@ fn main() {
2929

3030
let sized = &1 as *const i32;
3131
sized.offset(0);
32+
33+
let nn = core::ptr::NonNull::<()>::dangling();
34+
nn.add(0);
35+
//~^ zst_offset
36+
37+
nn.offset(0);
38+
//~^ zst_offset
39+
40+
nn.sub(0);
41+
//~^ zst_offset
42+
43+
let nn_sized = core::ptr::NonNull::<i32>::dangling();
44+
nn_sized.add(0);
3245
}
3346
}

tests/ui/zero_offset.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,23 @@ error: offset calculation on zero-sized value
4848
LL | c.wrapping_sub(0);
4949
| ^^^^^^^^^^^^^^^^^
5050

51-
error: aborting due to 8 previous errors
51+
error: offset calculation on zero-sized value
52+
--> tests/ui/zero_offset.rs:34:9
53+
|
54+
LL | nn.add(0);
55+
| ^^^^^^^^^
56+
57+
error: offset calculation on zero-sized value
58+
--> tests/ui/zero_offset.rs:37:9
59+
|
60+
LL | nn.offset(0);
61+
| ^^^^^^^^^^^^
62+
63+
error: offset calculation on zero-sized value
64+
--> tests/ui/zero_offset.rs:40:9
65+
|
66+
LL | nn.sub(0);
67+
| ^^^^^^^^^
68+
69+
error: aborting due to 11 previous errors
5270

0 commit comments

Comments
 (0)