mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-12-13 14:52:46 +00:00
66 lines
2 KiB
Rust
66 lines
2 KiB
Rust
|
use clippy_utils::diagnostics::span_lint;
|
||
|
use rustc_ast::ast::{Expr, ExprKind, Stmt, StmtKind};
|
||
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||
|
|
||
|
declare_clippy_lint! {
|
||
|
/// ### What it does
|
||
|
/// Checks for nested assignments.
|
||
|
///
|
||
|
/// ### Why is this bad?
|
||
|
/// While this is in most cases already a type mismatch,
|
||
|
/// the result of an assignment being `()` can throw off people coming from languages like python or C,
|
||
|
/// where such assignments return a copy of the assigned value.
|
||
|
///
|
||
|
/// ### Example
|
||
|
/// ```rust
|
||
|
///# let (a, b);
|
||
|
/// a = b = 42;
|
||
|
/// ```
|
||
|
/// Use instead:
|
||
|
/// ```rust
|
||
|
///# let (a, b);
|
||
|
/// b = 42;
|
||
|
/// a = b;
|
||
|
/// ```
|
||
|
#[clippy::version = "1.65.0"]
|
||
|
pub MULTI_ASSIGNMENTS,
|
||
|
suspicious,
|
||
|
"instead of using `a = b = c;` use `a = c; b = c;`"
|
||
|
}
|
||
|
|
||
|
declare_lint_pass!(MultiAssignments => [MULTI_ASSIGNMENTS]);
|
||
|
|
||
|
fn strip_paren_blocks(expr: &Expr) -> &Expr {
|
||
|
match &expr.kind {
|
||
|
ExprKind::Paren(e) => strip_paren_blocks(e),
|
||
|
ExprKind::Block(b, _) => {
|
||
|
if let [
|
||
|
Stmt {
|
||
|
kind: StmtKind::Expr(e),
|
||
|
..
|
||
|
},
|
||
|
] = &b.stmts[..]
|
||
|
{
|
||
|
strip_paren_blocks(e)
|
||
|
} else {
|
||
|
expr
|
||
|
}
|
||
|
},
|
||
|
_ => expr,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl EarlyLintPass for MultiAssignments {
|
||
|
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
||
|
if let ExprKind::Assign(target, source, _) = &expr.kind {
|
||
|
if let ExprKind::Assign(_target, _source, _) = &strip_paren_blocks(target).kind {
|
||
|
span_lint(cx, MULTI_ASSIGNMENTS, expr.span, "assignments don't nest intuitively");
|
||
|
};
|
||
|
if let ExprKind::Assign(_target, _source, _) = &strip_paren_blocks(source).kind {
|
||
|
span_lint(cx, MULTI_ASSIGNMENTS, expr.span, "assignments don't nest intuitively");
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|