Box ExprKind::{Closure,MethodCall}, and QSelf in expressions, types, and patterns.

This commit is contained in:
Nicholas Nethercote 2022-09-08 10:52:51 +10:00
parent cbd6159095
commit 333b92c5ed
8 changed files with 50 additions and 28 deletions

View File

@ -61,10 +61,10 @@ impl EarlyLintPass for DoubleParens {
} }
} }
}, },
ExprKind::MethodCall(_, _, ref params, _) => { ExprKind::MethodCall(ref call) => {
if let [ref param] = params[..] { if let [ref arg] = call.args[..] {
if let ExprKind::Paren(_) = param.kind { if let ExprKind::Paren(_) = arg.kind {
span_lint(cx, DOUBLE_PARENS, param.span, msg); span_lint(cx, DOUBLE_PARENS, arg.span, msg);
} }
} }
}, },

View File

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_direct_expn_of; use clippy_utils::is_direct_expn_of;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::ast::{Expr, ExprKind}; use rustc_ast::ast::{Expr, ExprKind, MethodCall};
use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym; use rustc_span::sym;
@ -37,8 +37,8 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
impl EarlyLintPass for OptionEnvUnwrap { impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind; if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind;
if matches!(path_segment.ident.name, sym::expect | sym::unwrap); if matches!(seg.ident.name, sym::expect | sym::unwrap);
if let ExprKind::Call(caller, _) = &receiver.kind; if let ExprKind::Call(caller, _) = &receiver.kind;
if is_direct_expn_of(caller.span, "option_env").is_some(); if is_direct_expn_of(caller.span, "option_env").is_some();
then { then {

View File

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp};
use rustc_ast::token; use rustc_ast::token;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_lint::{EarlyContext, EarlyLintPass};
@ -110,11 +110,11 @@ impl EarlyLintPass for Precedence {
let mut arg = operand; let mut arg = operand;
let mut all_odd = true; let mut all_odd = true;
while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind { while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind {
let path_segment_str = path_segment.ident.name.as_str(); let seg_str = seg.ident.name.as_str();
all_odd &= ALLOWED_ODD_FUNCTIONS all_odd &= ALLOWED_ODD_FUNCTIONS
.iter() .iter()
.any(|odd_function| **odd_function == *path_segment_str); .any(|odd_function| **odd_function == *seg_str);
arg = receiver; arg = receiver;
} }

View File

@ -69,10 +69,10 @@ impl EarlyLintPass for RedundantClosureCall {
if_chain! { if_chain! {
if let ast::ExprKind::Call(ref paren, _) = expr.kind; if let ast::ExprKind::Call(ref paren, _) = expr.kind;
if let ast::ExprKind::Paren(ref closure) = paren.kind; if let ast::ExprKind::Paren(ref closure) = paren.kind;
if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind; if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind;
then { then {
let mut visitor = ReturnVisitor::new(); let mut visitor = ReturnVisitor::new();
visitor.visit_expr(block); visitor.visit_expr(body);
if !visitor.found_return { if !visitor.found_return {
span_lint_and_then( span_lint_and_then(
cx, cx,
@ -80,13 +80,13 @@ impl EarlyLintPass for RedundantClosureCall {
expr.span, expr.span,
"try not to call a closure in the expression where it is declared", "try not to call a closure in the expression where it is declared",
|diag| { |diag| {
if decl.inputs.is_empty() { if fn_decl.inputs.is_empty() {
let app = Applicability::MachineApplicable; let app = Applicability::MachineApplicable;
let mut hint = Sugg::ast(cx, block, ".."); let mut hint = Sugg::ast(cx, body, "..");
if r#async.is_async() { if asyncness.is_async() {
// `async x` is a syntax error, so it becomes `async { x }` // `async x` is a syntax error, so it becomes `async { x }`
if !matches!(block.kind, ast::ExprKind::Block(_, _)) { if !matches!(body.kind, ast::ExprKind::Block(_, _)) {
hint = hint.blockify(); hint = hint.blockify();
} }

View File

@ -580,7 +580,7 @@ fn ident_difference_expr_with_base_location(
| (Await(_), Await(_)) | (Await(_), Await(_))
| (Async(_, _, _), Async(_, _, _)) | (Async(_, _, _), Async(_, _, _))
| (Block(_, _), Block(_, _)) | (Block(_, _), Block(_, _))
| (Closure(_, _, _, _, _, _, _), Closure(_, _, _, _, _, _, _)) | (Closure(_), Closure(_))
| (Match(_, _), Match(_, _)) | (Match(_, _), Match(_, _))
| (Loop(_, _), Loop(_, _)) | (Loop(_, _), Loop(_, _))
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _)) | (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
@ -593,7 +593,7 @@ fn ident_difference_expr_with_base_location(
| (Unary(_, _), Unary(_, _)) | (Unary(_, _), Unary(_, _))
| (Binary(_, _, _), Binary(_, _, _)) | (Binary(_, _, _), Binary(_, _, _))
| (Tup(_), Tup(_)) | (Tup(_), Tup(_))
| (MethodCall(_, _, _, _), MethodCall(_, _, _, _)) | (MethodCall(_), MethodCall(_))
| (Call(_, _), Call(_, _)) | (Call(_, _), Call(_, _))
| (ConstBlock(_), ConstBlock(_)) | (ConstBlock(_), ConstBlock(_))
| (Array(_), Array(_)) | (Array(_), Array(_))

View File

@ -292,7 +292,7 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize)
/// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern /// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
/// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal. /// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
fn extend_with_struct_pat( fn extend_with_struct_pat(
qself1: &Option<ast::QSelf>, qself1: &Option<P<ast::QSelf>>,
path1: &ast::Path, path1: &ast::Path,
fps1: &mut [ast::PatField], fps1: &mut [ast::PatField],
rest1: bool, rest1: bool,

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::ast::{Expr, ExprKind}; use rustc_ast::ast::{Expr, ExprKind, MethodCall};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -30,8 +30,8 @@ declare_clippy_lint! {
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]); declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> { fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
&& let method_name = name_ident.ident.name.as_str() && let method_name = seg.ident.name.as_str()
&& (method_name == "ceil" || method_name == "round" || method_name == "floor") && (method_name == "ceil" || method_name == "round" || method_name == "floor")
&& let ExprKind::Lit(token_lit) = &receiver.kind && let ExprKind::Lit(token_lit) = &receiver.kind
&& token_lit.is_semantic_float() { && token_lit.is_semantic_float() {

View File

@ -75,11 +75,11 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool {
&& over(&l.attrs, &r.attrs, eq_attr) && over(&l.attrs, &r.attrs, eq_attr)
} }
pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool { pub fn eq_qself(l: &P<QSelf>, r: &P<QSelf>) -> bool {
l.position == r.position && eq_ty(&l.ty, &r.ty) l.position == r.position && eq_ty(&l.ty, &r.ty)
} }
pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool { pub fn eq_maybe_qself(l: &Option<P<QSelf>>, r: &Option<P<QSelf>>) -> bool {
match (l, r) { match (l, r) {
(Some(l), Some(r)) => eq_qself(l, r), (Some(l), Some(r)) => eq_qself(l, r),
(None, None) => true, (None, None) => true,
@ -147,8 +147,11 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)), (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value), (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
(Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)), (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
(MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => { (
eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r)) MethodCall(box ast::MethodCall { seg: ls, receiver: lr, args: la, .. }),
MethodCall(box ast::MethodCall { seg: rs, receiver: rr, args: ra, .. })
) => {
eq_path_seg(ls, rs) && eq_expr(lr, rr) && over(la, ra, |l, r| eq_expr(l, r))
}, },
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr), (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r), (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
@ -170,7 +173,26 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv), (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
(Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp), (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
(Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm), (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
(Closure(lb, lc, la, lm, lf, le, _), Closure(rb, rc, ra, rm, rf, re, _)) => { (
Closure(box ast::Closure {
binder: lb,
capture_clause: lc,
asyncness: la,
movability: lm,
fn_decl: lf,
body: le,
..
}),
Closure(box ast::Closure {
binder: rb,
capture_clause: rc,
asyncness: ra,
movability: rm,
fn_decl: rf,
body: re,
..
})
) => {
eq_closure_binder(lb, rb) eq_closure_binder(lb, rb)
&& lc == rc && lc == rc
&& la.is_async() == ra.is_async() && la.is_async() == ra.is_async()