-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #9995
- Loading branch information
Showing
6 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use clippy_utils::diagnostics::span_lint_and_help; | ||
use clippy_utils::ty::peel_mid_ty_refs; | ||
use rustc_hir::{Expr, ExprKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
use rustc_span::sym; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// | ||
/// Checks for calls to `std::mem::size_of_val()` where the argument is | ||
/// a reference to a reference. | ||
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// The result of calling `size_of_val()` with a reference to a reference | ||
/// as the argument will be the size of any generic reference-type, not | ||
/// the size of the value behind the reference. | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// struct Foo { | ||
/// buffer: [u8], | ||
/// } | ||
/// | ||
/// impl Foo { | ||
/// fn size(&self) -> usize { | ||
/// // Note that `&self` as an argument is a `&&Foo`: Bacause `self` | ||
/// // is already a reference, `&self` is a double-reference, | ||
/// // and the return value of `size_of_val()` therefor is the | ||
/// // size of any generic reference-type. | ||
/// std::mem::size_of_val(&self) | ||
/// } | ||
/// } | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// struct Foo { | ||
/// buffer: [u8], | ||
/// } | ||
/// | ||
/// impl Foo { | ||
/// fn size(&self) -> usize { | ||
/// // Correct | ||
/// std::mem::size_of_val(self) | ||
/// } | ||
/// } | ||
/// ``` | ||
#[clippy::version = "1.67.0"] | ||
pub SIZE_OF_REF, | ||
correctness, | ||
"Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended" | ||
} | ||
declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); | ||
|
||
impl LateLintPass<'_> for SizeOfRef { | ||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { | ||
if let ExprKind::Call(path, [arg]) = expr.kind | ||
&& let ExprKind::Path(ref qpath) = path.kind | ||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() | ||
&& cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id) | ||
&& let arg_ty = cx.typeck_results().expr_ty(arg) | ||
&& peel_mid_ty_refs(arg_ty).1 > 1 | ||
{ | ||
span_lint_and_help( | ||
cx, | ||
SIZE_OF_REF, | ||
expr.span, | ||
"argument to `std::mem::size_of_val()` is a reference to a reference", | ||
None, | ||
"dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the generic size of any reference-type", | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#![allow(unused)] | ||
#![warn(clippy::size_of_ref)] | ||
|
||
use std::mem::size_of_val; | ||
|
||
fn main() { | ||
let x = 5; | ||
let y = &x; | ||
|
||
size_of_val(&x); // no lint | ||
size_of_val(y); // no lint | ||
|
||
size_of_val(&&x); | ||
size_of_val(&y); | ||
} | ||
|
||
struct S { | ||
field: u32, | ||
data: Vec<u8>, | ||
} | ||
|
||
impl S { | ||
/// Get size of object including `self`, in bytes. | ||
pub fn size(&self) -> usize { | ||
std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
error: argument to `std::mem::size_of_val()` is a reference to a reference | ||
--> $DIR/size_of_ref.rs:13:5 | ||
| | ||
LL | size_of_val(&&x); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the generic size of any reference-type | ||
= note: `-D clippy::size-of-ref` implied by `-D warnings` | ||
|
||
error: argument to `std::mem::size_of_val()` is a reference to a reference | ||
--> $DIR/size_of_ref.rs:14:5 | ||
| | ||
LL | size_of_val(&y); | ||
| ^^^^^^^^^^^^^^^ | ||
| | ||
= help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the generic size of any reference-type | ||
|
||
error: argument to `std::mem::size_of_val()` is a reference to a reference | ||
--> $DIR/size_of_ref.rs:25:9 | ||
| | ||
LL | std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the generic size of any reference-type | ||
|
||
error: aborting due to 3 previous errors | ||
|