Skip to content

Commit

Permalink
Keep working on PR rust-lang#5138
Browse files Browse the repository at this point in the history
  • Loading branch information
chansuke committed Jun 30, 2020
2 parents 88fec89 + 8ef21ba commit 075d1a9
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,7 @@ Released 2018-09-13
[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const
[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools
[`fn_param_redef_as_mutable`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_param_redef_as_mutable
[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map
Expand Down
96 changes: 96 additions & 0 deletions clippy_lints/src/fn_param_redef_as_mutable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use rustc_lint::{EarlyLintPass, EarlyContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use syntax::ast::*;
use syntax::visit::FnKind;
use rustc_span::Span;
use rustc_errors::DiagnosticBuilder;
use crate::utils::{span_lint_and_then, multispan_sugg};
use if_chain::if_chain;

declare_clippy_lint! {
/// **What it does:** checks if any fn parameters have been assigned to a local mutable
/// variable.
///
/// **Why is this bad?** reduces the complexity of the code by removing a redundant local
/// mutable variable.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust
/// fn f(a: Vec<bool>) {
/// let mut a = a;
/// // rest of code
/// }
/// ```
///
/// could be defined as
///
/// ```rust
/// fn f(mut a: Vec<bool>) {
/// // rest of code
/// }
/// ```
pub FN_PARAM_REDEF_AS_MUTABLE,
complexity,
"local variables that can be eliminated by updating fn params mutability"
}

declare_lint_pass!(FnParamRedefAsMutable => [FN_PARAM_REDEF_AS_MUTABLE]);

impl EarlyLintPass for FnParamRedefAsMutable {
fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, fn_decl: &FnDecl, span: Span, _: NodeId) {
if let FnKind::ItemFn(_, _, _, block) | FnKind::Method(_, _, _, block) = fn_kind {
for stmt in &block.stmts {
check_statement(cx, fn_decl, span, stmt);
}
}
}
}

fn check_statement(cx: &EarlyContext<'_>, fn_decl: &FnDecl, fn_span: Span, stmt: &Stmt) {
if_chain! {
// Check to see if the local variable is defined as mutable
if let StmtKind::Local(ref local) = stmt.kind;
if let PatKind::Ident(mode, ..) = local.pat.kind;
if let BindingMode::ByValue(mutability) = mode;
if let Mutability::Mut = mutability;

if let Some(ref expr) = local.init;
if let ExprKind::Path(_, ref path) = expr.kind;
if let Some(ref segment) = path.segments.last();
if let name = segment.ident.name;

// The path to fn parameters is 1 in length.
if path.segments.len() == 1;
then {
for param in &fn_decl.inputs {
if_chain! {
if let PatKind::Ident(param_mode, ident, ..) = param.pat.kind;
// Make sure they have the same name & it's not mutable
if ident.name == name;
if let BindingMode::ByValue(param_mut) = param_mode;
if let Mutability::Not = param_mut;

then {
let sugg = |db: &mut DiagnosticBuilder<'_>| {
db.span_help(param.span, "consider making this param `mut`");
db.span_help(stmt.span, "consider removing this local variable");

multispan_sugg(db, "...".to_string(), vec![]);
};

span_lint_and_then(
cx,
FN_PARAM_REDEF_AS_MUTABLE,
fn_span,
"a parameter was redefined as mutable, can be removed",
sugg,
);
}
}
}
}
}
}
4 changes: 4 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&float_literal::LOSSY_FLOAT_LITERAL,
&floating_point_arithmetic::IMPRECISE_FLOPS,
&floating_point_arithmetic::SUBOPTIMAL_FLOPS,
&fn_param_redef_as_mutable::FN_PARAM_REDEF_AS_MUTABLE,
&format::USELESS_FORMAT,
&formatting::POSSIBLE_MISSING_COMMA,
&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
Expand Down Expand Up @@ -1060,6 +1061,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns);
store.register_late_pass(|| box macro_use::MacroUseImports::default());
store.register_late_pass(|| box map_identity::MapIdentity);
store.register_early_pass(|| box fn_param_redef_as_mutable::FnParamRedefAsMutable);

store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
Expand Down Expand Up @@ -1230,6 +1232,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
LintId::of(&explicit_write::EXPLICIT_WRITE),
LintId::of(&float_literal::EXCESSIVE_PRECISION),
LintId::of(&fn_param_redef_as_mutable::FN_PARAM_REDEF_AS_MUTABLE),
LintId::of(&format::USELESS_FORMAT),
LintId::of(&formatting::POSSIBLE_MISSING_COMMA),
LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
Expand Down Expand Up @@ -1544,6 +1547,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
LintId::of(&explicit_write::EXPLICIT_WRITE),
LintId::of(&fn_param_redef_as_mutable::FN_PARAM_REDEF_AS_MUTABLE),
LintId::of(&format::USELESS_FORMAT),
LintId::of(&functions::TOO_MANY_ARGUMENTS),
LintId::of(&get_last_with_len::GET_LAST_WITH_LEN),
Expand Down
7 changes: 7 additions & 0 deletions src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
deprecation: None,
module: "excessive_bools",
},
Lint {
name: "fn_param_redef_as_mutable",
group: "complexity",
desc: "default lint description",
deprecation: None,
module: "fn_param_redef_as_mutable",
},
Lint {
name: "fn_to_numeric_cast",
group: "style",
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/fn_param_redef_as_mutable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![warn(clippy::fn_param_redef_as_mutable)]

fn foobar(a: Vec<bool>) {
let mut c = a;
}

fn main() {
}
22 changes: 22 additions & 0 deletions tests/ui/fn_param_redef_as_mutable.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error: a parameter was redefined as mutable, can be removed
--> $DIR/fn_param_redef_as_mutable.rs:3:1
|
LL | / fn foobar(a: Vec<bool>) {
LL | | let mut c = a;
LL | | }
| |_^
|
= note: `-D clippy::fn-param-redef-as-mutable` implied by `-D warnings`
help: consider making this param `mut`
--> $DIR/fn_param_redef_as_mutable.rs:3:11
|
LL | fn foobar(a: Vec<bool>) {
| ^^^^^^^^^^^^^
help: consider removing this local variable
--> $DIR/fn_param_redef_as_mutable.rs:4:5
|
LL | let mut c = a;
| ^^^^^^^^^^^^^^

error: aborting due to previous error

0 comments on commit 075d1a9

Please sign in to comment.