-
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.
- Loading branch information
Showing
7 changed files
with
204 additions
and
2 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,89 @@ | ||
use crate::rustc_target::abi::LayoutOf; | ||
use crate::utils::{snippet_opt, span_lint_and_then}; | ||
use if_chain::if_chain; | ||
use rustc::mir::interpret::ConstValue; | ||
use rustc::ty::{self, ConstKind}; | ||
use rustc_hir::{Item, ItemKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_session::{declare_tool_lint, impl_lint_pass}; | ||
use rustc_span::InnerSpan; | ||
use rustc_typeck::hir_ty_to_ty; | ||
|
||
declare_clippy_lint! { | ||
/// **What it does:** Checks for large `const` non-scalar types (ie: array) that should | ||
/// be defined as `static` instead. | ||
/// | ||
/// **Why is this bad?** Performance: const variables are inlined upon use. | ||
/// Static items result in only one instance and has a fixed location in memory. | ||
/// | ||
/// **Known problems:** None. | ||
/// | ||
/// **Example:** | ||
/// ```rust,ignore | ||
/// // Bad code | ||
/// pub const a = [0u32; 1_000_000]; | ||
/// | ||
/// // Good code | ||
/// pub static a = [0u32; 1_000_000]; | ||
/// ``` | ||
pub NON_SCALAR_CONST, | ||
perf, | ||
"large non-scalar const variable may cause performance overhead" | ||
} | ||
|
||
pub struct NonScalarConst { | ||
maximum_allowed_size: u64, | ||
} | ||
|
||
impl NonScalarConst { | ||
#[must_use] | ||
pub fn new(maximum_allowed_size: u64) -> Self { | ||
Self { maximum_allowed_size } | ||
} | ||
} | ||
|
||
impl_lint_pass!(NonScalarConst => [NON_SCALAR_CONST]); | ||
|
||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonScalarConst { | ||
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item<'_>) { | ||
// No suggestion in macros | ||
if it.span.from_expansion() { | ||
return; | ||
} | ||
if_chain! { | ||
if let ItemKind::Const(hir_ty, _) = &it.kind; | ||
let ty = hir_ty_to_ty(cx.tcx, hir_ty); | ||
if let ty::Array(element_type, cst) = ty.kind; | ||
if let ConstKind::Value(val) = cst.val; | ||
if let ConstValue::Scalar(element_count) = val; | ||
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx); | ||
if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes()); | ||
if self.maximum_allowed_size < element_count * element_size; | ||
then { | ||
// We need to take care about the right "const" position inside the span | ||
let mut start_sugg = 0; | ||
if let Some(visi) = snippet_opt(cx, it.vis.span) { | ||
let len_visi = visi.len(); | ||
if len_visi > 0 { | ||
start_sugg = len_visi + 1; | ||
} | ||
} | ||
let sugg_span = it.span.from_inner( | ||
InnerSpan::new(start_sugg, start_sugg + "const".len()) | ||
); | ||
span_lint_and_then( | ||
cx, | ||
NON_SCALAR_CONST, | ||
sugg_span, | ||
"large array defined as const", | ||
|db| { | ||
db.span_label( | ||
it.span, | ||
"make this item static" | ||
); | ||
} | ||
); | ||
} | ||
} | ||
} | ||
} |
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,34 @@ | ||
#![warn(clippy::non_scalar_const)] | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct S { | ||
pub data: [u64; 32], | ||
} | ||
|
||
// Should lint | ||
pub(crate) const FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
|
||
// Good | ||
pub(crate) const G_FOO_PUB_CRATE: [u32; 1_000] = [0u32; 1_000]; | ||
pub const G_FOO_PUB: [u32; 1_000] = [0u32; 1_000]; | ||
const G_FOO: [u32; 1_000] = [0u32; 1_000]; | ||
|
||
fn main() { | ||
// Should lint | ||
pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ||
const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ||
pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ||
const BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ||
|
||
// Good | ||
pub const G_BAR_PUB: [u32; 1_000] = [0u32; 1_000]; | ||
const G_BAR: [u32; 1_000] = [0u32; 1_000]; | ||
pub const G_BAR_STRUCT_PUB: [S; 500] = [S { data: [0; 32] }; 500]; | ||
const G_BAR_STRUCT: [S; 500] = [S { data: [0; 32] }; 500]; | ||
pub const G_BAR_S_PUB: [Option<&str>; 200] = [Some("str"); 200]; | ||
const G_BAR_S: [Option<&str>; 200] = [Some("str"); 200]; | ||
} |
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,66 @@ | ||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:9:12 | ||
| | ||
LL | pub(crate) const FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
| -----------^^^^^----------------------------------------------------- make this item static | ||
| | ||
= note: `-D clippy::non-scalar-const` implied by `-D warnings` | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:10:5 | ||
| | ||
LL | pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
| ----^^^^^----------------------------------------------- make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:11:1 | ||
| | ||
LL | const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
| ^^^^^------------------------------------------- | ||
| | | ||
| make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:20:9 | ||
| | ||
LL | pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
| ----^^^^^----------------------------------------------- make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:21:5 | ||
| | ||
LL | const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | ||
| ^^^^^------------------------------------------- | ||
| | | ||
| make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:22:9 | ||
| | ||
LL | pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ||
| ----^^^^^----------------------------------------------------------- make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:23:5 | ||
| | ||
LL | const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ||
| ^^^^^------------------------------------------------------- | ||
| | | ||
| make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:24:9 | ||
| | ||
LL | pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ||
| ----^^^^^------------------------------------------------------------- make this item static | ||
|
||
error: large array defined as const | ||
--> $DIR/non_scalar_const.rs:25:5 | ||
| | ||
LL | const BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ||
| ^^^^^--------------------------------------------------------- | ||
| | | ||
| make this item static | ||
|
||
error: aborting due to 9 previous errors | ||
|