1 use clippy_utils
::diagnostics
::span_lint_and_help
;
2 use clippy_utils
::path_def_id
;
3 use clippy_utils
::ty
::peel_mid_ty_refs
;
4 use rustc_hir
::{Expr, ExprKind}
;
5 use rustc_lint
::{LateContext, LateLintPass}
;
6 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
12 /// Checks for calls to `std::mem::size_of_val()` where the argument is
13 /// a reference to a reference.
15 /// ### Why is this bad?
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
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)
44 /// fn size(&self) -> usize {
46 /// std::mem::size_of_val(self)
50 #[clippy::version = "1.68.0"]
53 "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended"
55 declare_lint_pass
!(SizeOfRef
=> [SIZE_OF_REF
]);
57 impl 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
69 "argument to `std::mem::size_of_val()` is a reference to a reference",
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",