-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #5470 - flip1995:rollup-cvkuiza, r=flip1995
Rollup of 5 pull requests Successful merges: - #5226 (Add lint for explicit deref and deref_mut method calls) - #5248 (Add lint on large non scalar const) - #5430 (Disallow bit-shifting in integer_arithmetic) - #5466 (large_enum_variant: Report sizes of variants) - #5468 (Zero single char names) Failed merges: r? @ghost changelog: rollup
- Loading branch information
Showing
21 changed files
with
731 additions
and
39 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg}; | ||
use if_chain::if_chain; | ||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX}; | ||
use rustc_errors::Applicability; | ||
use rustc_hir::{Expr, ExprKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
use rustc_span::source_map::Span; | ||
|
||
declare_clippy_lint! { | ||
/// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls. | ||
/// | ||
/// **Why is this bad?** Derefencing by `&*x` or `&mut *x` is clearer and more concise, | ||
/// when not part of a method chain. | ||
/// | ||
/// **Example:** | ||
/// ```rust | ||
/// use std::ops::Deref; | ||
/// let a: &mut String = &mut String::from("foo"); | ||
/// let b: &str = a.deref(); | ||
/// ``` | ||
/// Could be written as: | ||
/// ```rust | ||
/// let a: &mut String = &mut String::from("foo"); | ||
/// let b = &*a; | ||
/// ``` | ||
/// | ||
/// This lint excludes | ||
/// ```rust,ignore | ||
/// let _ = d.unwrap().deref(); | ||
/// ``` | ||
pub EXPLICIT_DEREF_METHODS, | ||
pedantic, | ||
"Explicit use of deref or deref_mut method while not in a method chain." | ||
} | ||
|
||
declare_lint_pass!(Dereferencing => [ | ||
EXPLICIT_DEREF_METHODS | ||
]); | ||
|
||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing { | ||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { | ||
if_chain! { | ||
if !expr.span.from_expansion(); | ||
if let ExprKind::MethodCall(ref method_name, _, ref args) = &expr.kind; | ||
if args.len() == 1; | ||
|
||
then { | ||
if let Some(parent_expr) = get_parent_expr(cx, expr) { | ||
// Check if we have the whole call chain here | ||
if let ExprKind::MethodCall(..) = parent_expr.kind { | ||
return; | ||
} | ||
// Check for Expr that we don't want to be linted | ||
let precedence = parent_expr.precedence(); | ||
match precedence { | ||
// Lint a Call is ok though | ||
ExprPrecedence::Call | ExprPrecedence::AddrOf => (), | ||
_ => { | ||
if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX { | ||
return; | ||
} | ||
} | ||
} | ||
} | ||
let name = method_name.ident.as_str(); | ||
lint_deref(cx, &*name, &args[0], args[0].span, expr.span); | ||
} | ||
} | ||
} | ||
} | ||
|
||
fn lint_deref(cx: &LateContext<'_, '_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) { | ||
match method_name { | ||
"deref" => { | ||
if cx | ||
.tcx | ||
.lang_items() | ||
.deref_trait() | ||
.map_or(false, |id| implements_trait(cx, cx.tables.expr_ty(&call_expr), id, &[])) | ||
{ | ||
span_lint_and_sugg( | ||
cx, | ||
EXPLICIT_DEREF_METHODS, | ||
expr_span, | ||
"explicit deref method call", | ||
"try this", | ||
format!("&*{}", &snippet(cx, var_span, "..")), | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
}, | ||
"deref_mut" => { | ||
if cx | ||
.tcx | ||
.lang_items() | ||
.deref_mut_trait() | ||
.map_or(false, |id| implements_trait(cx, cx.tables.expr_ty(&call_expr), id, &[])) | ||
{ | ||
span_lint_and_sugg( | ||
cx, | ||
EXPLICIT_DEREF_METHODS, | ||
expr_span, | ||
"explicit deref_mut method call", | ||
"try this", | ||
format!("&mut *{}", &snippet(cx, var_span, "..")), | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
}, | ||
_ => (), | ||
} | ||
} |
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,85 @@ | ||
use crate::rustc_target::abi::LayoutOf; | ||
use crate::utils::span_lint_and_then; | ||
use if_chain::if_chain; | ||
use rustc_errors::Applicability; | ||
use rustc_hir::{Item, ItemKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_middle::mir::interpret::ConstValue; | ||
use rustc_middle::ty::{self, ConstKind}; | ||
use rustc_session::{declare_tool_lint, impl_lint_pass}; | ||
use rustc_span::{BytePos, Pos, Span}; | ||
use rustc_typeck::hir_ty_to_ty; | ||
|
||
declare_clippy_lint! { | ||
/// **What it does:** Checks for large `const` arrays 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 | ||
/// pub const a = [0u32; 1_000_000]; | ||
/// | ||
/// // Good | ||
/// pub static a = [0u32; 1_000_000]; | ||
/// ``` | ||
pub LARGE_CONST_ARRAYS, | ||
perf, | ||
"large non-scalar const array may cause performance overhead" | ||
} | ||
|
||
pub struct LargeConstArrays { | ||
maximum_allowed_size: u64, | ||
} | ||
|
||
impl LargeConstArrays { | ||
#[must_use] | ||
pub fn new(maximum_allowed_size: u64) -> Self { | ||
Self { maximum_allowed_size } | ||
} | ||
} | ||
|
||
impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]); | ||
|
||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeConstArrays { | ||
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { | ||
if_chain! { | ||
if !item.span.from_expansion(); | ||
if let ItemKind::Const(hir_ty, _) = &item.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 { | ||
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); | ||
let sugg_span = Span::new( | ||
hi_pos - BytePos::from_usize("const".len()), | ||
hi_pos, | ||
item.span.ctxt(), | ||
); | ||
span_lint_and_then( | ||
cx, | ||
LARGE_CONST_ARRAYS, | ||
item.span, | ||
"large array defined as const", | ||
|db| { | ||
db.span_suggestion( | ||
sugg_span, | ||
"make this a static item", | ||
"static".to_string(), | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
); | ||
} | ||
} | ||
} | ||
} |
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
Oops, something went wrong.