]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/size_of_ref.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / size_of_ref.rs
CommitLineData
add651ee
FG
1use clippy_utils::diagnostics::span_lint_and_help;
2use clippy_utils::path_def_id;
3use clippy_utils::ty::peel_mid_ty_refs;
9c376795
FG
4use rustc_hir::{Expr, ExprKind};
5use rustc_lint::{LateContext, LateLintPass};
6use rustc_session::{declare_lint_pass, declare_tool_lint};
7use rustc_span::sym;
8
9declare_clippy_lint! {
10 /// ### What it does
11 ///
12 /// Checks for calls to `std::mem::size_of_val()` where the argument is
13 /// a reference to a reference.
14 ///
15 /// ### Why is this bad?
16 ///
17 /// Calling `size_of_val()` with a reference to a reference as the argument
18 /// yields the size of the reference-type, not the size of the value behind
19 /// the reference.
20 ///
21 /// ### Example
ed00b5ec 22 /// ```no_run
9c376795
FG
23 /// struct Foo {
24 /// buffer: [u8],
25 /// }
26 ///
27 /// impl Foo {
28 /// fn size(&self) -> usize {
29 /// // Note that `&self` as an argument is a `&&Foo`: Because `self`
30 /// // is already a reference, `&self` is a double-reference.
31 /// // The return value of `size_of_val()` therefor is the
32 /// // size of the reference-type, not the size of `self`.
33 /// std::mem::size_of_val(&self)
34 /// }
35 /// }
36 /// ```
37 /// Use instead:
ed00b5ec 38 /// ```no_run
9c376795
FG
39 /// struct Foo {
40 /// buffer: [u8],
41 /// }
42 ///
43 /// impl Foo {
44 /// fn size(&self) -> usize {
45 /// // Correct
46 /// std::mem::size_of_val(self)
47 /// }
48 /// }
49 /// ```
353b0b11 50 #[clippy::version = "1.68.0"]
9c376795
FG
51 pub SIZE_OF_REF,
52 suspicious,
53 "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended"
54}
55declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]);
56
57impl LateLintPass<'_> for SizeOfRef {
58 fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
59 if let ExprKind::Call(path, [arg]) = expr.kind
60 && let Some(def_id) = path_def_id(cx, path)
61 && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id)
62 && let arg_ty = cx.typeck_results().expr_ty(arg)
63 && peel_mid_ty_refs(arg_ty).1 > 1
64 {
65 span_lint_and_help(
66 cx,
67 SIZE_OF_REF,
68 expr.span,
69 "argument to `std::mem::size_of_val()` is a reference to a reference",
70 None,
71 "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type",
72 );
73 }
74 }
75}