diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index 15e00c7d7ce4c..2bc275ceff0be 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -66,7 +66,7 @@ Starting with an `expr`, you can check whether it is calling a specific method impl<'tcx> LateLintPass<'tcx> for MyStructLint { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { // Check our expr is calling a method - if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind + if let hir::ExprKind::MethodCall(path, _, _self_arg, ..) = &expr.kind // Check the name of this method is `some_method` && path.ident.name == sym!(some_method) // Optionally, check the type of the self argument. diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8a6bd1cbdf564..82574a8e64b0a 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(let_chains)] #![feature(let_else)] #![feature(once_cell)] #![feature(rustc_private)] diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs index 6a6554f968b33..7cd198ace86c0 100644 --- a/clippy_lints/src/assertions_on_result_states.rs +++ b/clippy_lints/src/assertions_on_result_states.rs @@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates { && matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro)) && let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) && matches!(panic_expn, PanicExpn::Empty) - && let ExprKind::MethodCall(method_segment, [recv], _) = condition.kind + && let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind && let result_type_with_refs = cx.typeck_results().expr_ty(recv) && let result_type = result_type_with_refs.peel_refs() && is_type_diagnostic_item(cx, result_type, sym::Result) diff --git a/clippy_lints/src/async_yields_async.rs b/clippy_lints/src/async_yields_async.rs index 27c2896e1e5ce..9464694a3b55a 100644 --- a/clippy_lints/src/async_yields_async.rs +++ b/clippy_lints/src/async_yields_async.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { hir_id: body.value.hir_id, }; let typeck_results = cx.tcx.typeck_body(body_id); - let expr_ty = typeck_results.expr_ty(&body.value); + let expr_ty = typeck_results.expr_ty(body.value); if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { let return_expr_span = match &body.value.kind { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 4bcbeacf9feb5..732dc2b433091 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -475,7 +475,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn(_, _, eid) = item.kind { - is_relevant_expr(cx, cx.tcx.typeck_body(eid), &cx.tcx.hir().body(eid).value) + is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) } else { true } @@ -483,7 +483,7 @@ fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool { match item.kind { - ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), &cx.tcx.hir().body(eid).value), + ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value), _ => false, } } @@ -492,7 +492,7 @@ fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { match item.kind { TraitItemKind::Fn(_, TraitFn::Required(_)) => true, TraitItemKind::Fn(_, TraitFn::Provided(eid)) => { - is_relevant_expr(cx, cx.tcx.typeck_body(eid), &cx.tcx.hir().body(eid).value) + is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) }, _ => false, } diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs index ad206b5fb304f..4df4d6ddf4167 100644 --- a/clippy_lints/src/blocks_in_if_conditions.rs +++ b/clippy_lints/src/blocks_in_if_conditions.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { // do not lint if the closure is called using an iterator (see #1141) if_chain! { if let Some(parent) = get_parent_expr(self.cx, expr); - if let ExprKind::MethodCall(_, [self_arg, ..], _) = &parent.kind; + if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind; let caller = self.cx.typeck_results().expr_ty(self_arg); if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator); if implements_trait(self.cx, caller, iter_id, &[]); diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 6eb78d21e8266..656d639f0efd9 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -270,8 +270,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { )) }) }, - ExprKind::MethodCall(path, args, _) if args.len() == 1 => { - let type_of_receiver = cx.typeck_results().expr_ty(&args[0]); + ExprKind::MethodCall(path, receiver, [], _) => { + let type_of_receiver = cx.typeck_results().expr_ty(receiver); if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option) && !is_type_diagnostic_item(cx, type_of_receiver, sym::Result) { @@ -285,7 +285,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { let path: &str = path.ident.name.as_str(); a == path }) - .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method))) + .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method))) }, _ => None, } diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index 6426e8c25ac1c..3f1edabe6c504 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -20,7 +20,7 @@ pub(super) fn check( if meets_msrv(msrv, msrvs::UNSIGNED_ABS) && let ty::Int(from) = cast_from.kind() && let ty::Uint(to) = cast_to.kind() - && let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind + && let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind && method_path.ident.name.as_str() == "abs" { let span = if from.bit_width() == to.bit_width() { @@ -37,7 +37,7 @@ pub(super) fn check( span, &format!("casting the result of `{cast_from}::abs()` to {cast_to}"), "replace with", - format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..").maybe_par()), + format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 64f87c80f8d14..406547a4454e6 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -44,7 +44,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))), _ => nbits, }, - ExprKind::MethodCall(method, [left, right], _) => { + ExprKind::MethodCall(method, left, [right], _) => { if signed { return nbits; } @@ -55,7 +55,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b }; apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value())) }, - ExprKind::MethodCall(method, [_, lo, hi], _) => { + ExprKind::MethodCall(method, _, [lo, hi], _) => { if method.ident.as_str() == "clamp" { //FIXME: make this a diagnostic item if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) { @@ -64,7 +64,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b } nbits }, - ExprKind::MethodCall(method, [_value], _) => { + ExprKind::MethodCall(method, _value, [], _) => { if method.ident.name.as_str() == "signum" { 0 // do not lint if cast comes from a `signum` function } else { diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs index d476a1a7646c0..da7b12f67266a 100644 --- a/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { cx.typeck_results().expr_ty(expr), ); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); - } else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind { + } else if let ExprKind::MethodCall(method_path, self_arg, ..) = &expr.kind { if method_path.ident.name == sym!(cast) && let Some(generic_args) = method_path.args && let [GenericArg::Type(cast_to)] = generic_args.args @@ -64,7 +64,7 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { return false; }; match parent.kind { - ExprKind::MethodCall(name, [self_arg, ..], _) if self_arg.hir_id == e.hir_id => { + ExprKind::MethodCall(name, self_arg, ..) if self_arg.hir_id == e.hir_id => { if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned") && let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id) && let Some(def_id) = cx.tcx.impl_of_method(def_id) diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 75f70b77ed4e7..5b59350be042c 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -41,14 +41,14 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast } // Don't lint for the result of methods that always return non-negative values. - if let ExprKind::MethodCall(path, _, _) = cast_op.kind { + if let ExprKind::MethodCall(path, ..) = cast_op.kind { let mut method_name = path.ident.name.as_str(); let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; if_chain! { if method_name == "unwrap"; if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]); - if let ExprKind::MethodCall(inner_path, _, _) = &arglist[0][0].kind; + if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind; then { method_name = inner_path.ident.name.as_str(); } diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index fb418a3251f58..be02f328e989a 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -131,10 +131,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { } }, - ExprKind::MethodCall(_, args, _) => { + ExprKind::MethodCall(_, receiver, args, _) => { if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) { let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder(); - for (expr, bound) in iter::zip(*args, fn_sig.inputs()) { + for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) { self.ty_bounds.push(TyBound::Ty(*bound)); self.visit_expr(expr); self.ty_bounds.pop(); diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 1506ea604f0dd..88e28018e5d00 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -503,7 +503,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { } fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { - if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind { + if let PatKind::Binding(BindingAnnotation::REF, id, name, _) = pat.kind { if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) { // This binding id has been seen before. Add this pattern to the list of changes. if let Some(prev_pat) = opt_prev_pat { @@ -581,7 +581,7 @@ fn try_parse_ref_op<'tcx>( expr: &'tcx Expr<'_>, ) -> Option<(RefOp, &'tcx Expr<'tcx>)> { let (def_id, arg) = match expr.kind { - ExprKind::MethodCall(_, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg), + ExprKind::MethodCall(_, arg, [], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg), ExprKind::Call( Expr { kind: ExprKind::Path(path), @@ -796,56 +796,54 @@ fn walk_parents<'tcx>( }, }) }), - ExprKind::MethodCall(_, args, _) => { + ExprKind::MethodCall(_, receiver, args, _) => { let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(); - args.iter().position(|arg| arg.hir_id == child_id).map(|i| { - if i == 0 { - // Check for calls to trait methods where the trait is implemented on a reference. - // Two cases need to be handled: - // * `self` methods on `&T` will never have auto-borrow - // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take - // priority. - if e.hir_id != child_id { - Position::ReborrowStable(precedence) - } else if let Some(trait_id) = cx.tcx.trait_of_item(id) - && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e)) - && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() - && let subs = match cx - .typeck_results() - .node_substs_opt(parent.hir_id) - .and_then(|subs| subs.get(1..)) - { - Some(subs) => cx.tcx.mk_substs(subs.iter().copied()), - None => cx.tcx.mk_substs(std::iter::empty::>()), - } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() { - // Trait methods taking `&self` - sub_ty - } else { - // Trait methods taking `self` - arg_ty - } && impl_ty.is_ref() - && cx.tcx.infer_ctxt().enter(|infcx| - infcx - .type_implements_trait(trait_id, impl_ty, subs, cx.param_env) - .must_apply_modulo_regions() - ) + if receiver.hir_id == child_id { + // Check for calls to trait methods where the trait is implemented on a reference. + // Two cases need to be handled: + // * `self` methods on `&T` will never have auto-borrow + // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take + // priority. + if e.hir_id != child_id { + return Some(Position::ReborrowStable(precedence)) + } else if let Some(trait_id) = cx.tcx.trait_of_item(id) + && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e)) + && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() + && let subs = match cx + .typeck_results() + .node_substs_opt(parent.hir_id) + .and_then(|subs| subs.get(1..)) { - Position::MethodReceiverRefImpl + Some(subs) => cx.tcx.mk_substs(subs.iter().copied()), + None => cx.tcx.mk_substs(std::iter::empty::>()), + } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() { + // Trait methods taking `&self` + sub_ty } else { - Position::MethodReceiver - } + // Trait methods taking `self` + arg_ty + } && impl_ty.is_ref() + && cx.tcx.infer_ctxt().enter(|infcx| + infcx + .type_implements_trait(trait_id, impl_ty, subs, cx.param_env) + .must_apply_modulo_regions() + ) + { + return Some(Position::MethodReceiverRefImpl) + } + return Some(Position::MethodReceiver); + } + args.iter().position(|arg| arg.hir_id == child_id).map(|i| { + let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1]; + if let ty::Param(param_ty) = ty.kind() { + needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv) } else { - let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i]; - if let ty::Param(param_ty) = ty.kind() { - needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv) - } else { - ty_auto_deref_stability( - cx, - cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)), - precedence, - ) - .position_for_arg() - } + ty_auto_deref_stability( + cx, + cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)), + precedence, + ) + .position_for_arg() } }) }, @@ -1174,7 +1172,7 @@ fn replace_types<'tcx>( if replaced.insert(param_ty.index) { for projection_predicate in projection_predicates { if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx) - && let ty::Term::Ty(term_ty) = projection_predicate.term + && let Some(term_ty) = projection_predicate.term.ty() && let ty::Param(term_param_ty) = term_ty.kind() { let item_def_id = projection_predicate.projection_ty.item_def_id; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index da111e7378eaf..eb158d850fa72 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -236,7 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { typeck_results: cx.tcx.typeck(item.def_id), panic_span: None, }; - fpu.visit_expr(&body.value); + fpu.visit_expr(body.value); lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } }, @@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { typeck_results: cx.tcx.typeck(item.def_id), panic_span: None, }; - fpu.visit_expr(&body.value); + fpu.visit_expr(body.value); lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } } @@ -348,7 +348,7 @@ fn lint_for_missing_headers<'tcx>( if let Some(future) = cx.tcx.lang_items().future_trait(); let typeck = cx.tcx.typeck_body(body_id); let body = cx.tcx.hir().body(body_id); - let ret_ty = typeck.expr_ty(&body.value); + let ret_ty = typeck.expr_ty(body.value); if implements_trait(cx, ret_ty, future, &[]); if let ty::Opaque(_, subs) = ret_ty.kind(); if let Some(gen) = subs.types().next(); @@ -828,7 +828,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); + let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 4e3ae4c961411..e70df3f53c75d 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -245,8 +245,8 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio match expr.kind { ExprKind::MethodCall( _, + map, [ - map, Expr { kind: ExprKind::AddrOf(_, _, key), span: key_span, @@ -280,7 +280,7 @@ struct InsertExpr<'tcx> { value: &'tcx Expr<'tcx>, } fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option> { - if let ExprKind::MethodCall(_, [map, key, value], _) = expr.kind { + if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) { Some(InsertExpr { map, key, value }) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 4f9ff97f1fd1a..53bc617a4f5b7 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { }; if body.value.span.from_expansion() { if body.params.is_empty() { - if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, &body.value) { + if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, body.value) { // replace `|| vec![]` with `Vec::new` span_lint_and_sugg( cx, @@ -103,10 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { let closure_ty = cx.typeck_results().expr_ty(expr); if_chain!( - if !is_adjusted(cx, &body.value); + if !is_adjusted(cx, body.value); if let ExprKind::Call(callee, args) = body.value.kind; if let ExprKind::Path(_) = callee.kind; - if check_inputs(cx, body.params, args); + if check_inputs(cx, body.params, None, args); let callee_ty = cx.typeck_results().expr_ty_adjusted(callee); let call_ty = cx.typeck_results().type_dependent_def_id(body.value.hir_id) .map_or(callee_ty, |id| cx.tcx.type_of(id)); @@ -145,9 +145,9 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { ); if_chain!( - if !is_adjusted(cx, &body.value); - if let ExprKind::MethodCall(path, args, _) = body.value.kind; - if check_inputs(cx, body.params, args); + if !is_adjusted(cx, body.value); + if let ExprKind::MethodCall(path, receiver, args, _) = body.value.kind; + if check_inputs(cx, body.params, Some(receiver), args); let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap(); let substs = cx.typeck_results().node_substs(body.value.hir_id); let call_ty = cx.tcx.bound_type_of(method_def_id).subst(cx.tcx, substs); @@ -167,12 +167,17 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { } } -fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_>]) -> bool { - if params.len() != call_args.len() { +fn check_inputs( + cx: &LateContext<'_>, + params: &[Param<'_>], + receiver: Option<&Expr<'_>>, + call_args: &[Expr<'_>], +) -> bool { + if receiver.map_or(params.len() != call_args.len(), |_| params.len() != call_args.len() + 1) { return false; } let binding_modes = cx.typeck_results().pat_binding_modes(); - std::iter::zip(params, call_args).all(|(param, arg)| { + let check_inputs = |param: &Param<'_>, arg| { match param.pat.kind { PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {}, _ => return false, @@ -200,7 +205,8 @@ fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_ }, _ => false, } - }) + }; + std::iter::zip(params, receiver.into_iter().chain(call_args.iter())).all(|(param, arg)| check_inputs(param, arg)) } fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tcx>) -> bool { diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 5bf4313b41a49..b9ed4af02190b 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -45,10 +45,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // match call to unwrap - if let ExprKind::MethodCall(unwrap_fun, [write_call], _) = expr.kind; + if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind; if unwrap_fun.ident.name == sym::unwrap; // match call to write_fmt - if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = look_in_block(cx, &write_call.kind); + if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind); if write_fun.ident.name == sym!(write_fmt); // match calls to std::io::stdout() / std::io::stderr () if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() { @@ -128,7 +128,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res); // Find id of the local we found in the block - if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind; // If those two are the same hir id if res_pat.hir_id == local_hir_id; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index b88e53aeca693..1f69f34a229df 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -84,7 +84,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); + let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result) { @@ -110,7 +110,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h typeck_results: cx.tcx.typeck(impl_item.id.def_id), result: Vec::new(), }; - fpu.visit_expr(&body.value); + fpu.visit_expr(body.value); // if we've found one, lint if !fpu.result.is_empty() { diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 9120507f48c85..ba53a9678801c 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -164,15 +164,15 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su suggestion.maybe_par() } -fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(method) = get_specialized_log_method(cx, &args[1]) { +fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(method) = get_specialized_log_method(cx, &args[0]) { span_lint_and_sugg( cx, SUBOPTIMAL_FLOPS, expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", - format!("{}.{}()", Sugg::hir(cx, &args[0], "..").maybe_par(), method), + format!("{}.{}()", Sugg::hir(cx, receiver, "..").maybe_par(), method), Applicability::MachineApplicable, ); } @@ -180,14 +180,14 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and // suggest usage of `(x + (y - 1)).ln_1p()` instead -fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { if let ExprKind::Binary( Spanned { node: BinOpKind::Add, .. }, lhs, rhs, - ) = &args[0].kind + ) = receiver.kind { let recv = match ( constant(cx, cx.typeck_results(), lhs), @@ -235,9 +235,9 @@ fn get_integer_from_float_constant(value: &Constant) -> Option { } } -fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver - if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) { + if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) { if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { Some("exp") } else if F32(2.0) == value || F64(2.0) == value { @@ -251,25 +251,25 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { expr.span, "exponent for bases 2 and e can be computed more accurately", "consider using", - format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method), + format!("{}.{}()", prepare_receiver_sugg(cx, &args[0]), method), Applicability::MachineApplicable, ); } } // Check argument - if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) { + if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) { let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { ( SUBOPTIMAL_FLOPS, "square-root of a number can be computed more efficiently and accurately", - format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..").maybe_par()), + format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_par()), ) } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { ( IMPRECISE_FLOPS, "cube-root of a number can be computed more accurately", - format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..").maybe_par()), + format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_par()), ) } else if let Some(exponent) = get_integer_from_float_constant(&value) { ( @@ -277,7 +277,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { "exponentiation with integer powers can be computed more efficiently", format!( "{}.powi({})", - Sugg::hir(cx, &args[0], "..").maybe_par(), + Sugg::hir(cx, receiver, "..").maybe_par(), numeric_literal::format(&exponent.to_string(), None, false) ), ) @@ -297,13 +297,14 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } -fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { - if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) { +fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) { if value == Int(2) { if let Some(parent) = get_parent_expr(cx, expr) { if let Some(grandparent) = get_parent_expr(cx, parent) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = grandparent.kind { - if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind + { + if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() { return; } } @@ -327,8 +328,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { "consider using", format!( "{}.mul_add({}, {})", - Sugg::hir(cx, &args[0], "..").maybe_par(), - Sugg::hir(cx, &args[0], ".."), + Sugg::hir(cx, receiver, "..").maybe_par(), + Sugg::hir(cx, receiver, ".."), Sugg::hir(cx, other_addend, ".."), ), Applicability::MachineApplicable, @@ -339,14 +340,14 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } -fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option { +fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { if let ExprKind::Binary( Spanned { node: BinOpKind::Add, .. }, add_lhs, add_rhs, - ) = args[0].kind + ) = receiver.kind { // check if expression of the form x * x + y * y if_chain! { @@ -363,12 +364,12 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option { if_chain! { if let ExprKind::MethodCall( PathSegment { ident: lmethod_name, .. }, - [largs_0, largs_1, ..], + largs_0, [largs_1, ..], _ ) = &add_lhs.kind; if let ExprKind::MethodCall( PathSegment { ident: rmethod_name, .. }, - [rargs_0, rargs_1, ..], + rargs_0, [rargs_1, ..], _ ) = &add_rhs.kind; if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; @@ -384,8 +385,8 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option { None } -fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(message) = detect_hypot(cx, args) { +fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { + if let Some(message) = detect_hypot(cx, receiver) { span_lint_and_sugg( cx, IMPRECISE_FLOPS, @@ -406,7 +407,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { if cx.typeck_results().expr_ty(lhs).is_floating_point(); if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs); if F32(1.0) == value || F64(1.0) == value; - if let ExprKind::MethodCall(path, [self_arg, ..], _) = &lhs.kind; + if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind; if cx.typeck_results().expr_ty(self_arg).is_floating_point(); if path.ident.name.as_str() == "exp"; then { @@ -450,8 +451,8 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { ) = &expr.kind { if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = parent.kind { - if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind { + if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() { return; } } @@ -586,14 +587,14 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, args_a, _) = expr_a.kind; - if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, args_b, _) = expr_b.kind; + if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind; + if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind; then { return method_name_a.as_str() == method_name_b.as_str() && args_a.len() == args_b.len() && ( ["ln", "log2", "log10"].contains(&method_name_a.as_str()) || - method_name_a.as_str() == "log" && args_a.len() == 2 && eq_expr_value(cx, &args_a[1], &args_b[1]) + method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0]) ); } } @@ -612,8 +613,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = &expr.kind; if are_same_base_logs(cx, lhs, rhs); - if let ExprKind::MethodCall(_, [largs_self, ..], _) = &lhs.kind; - if let ExprKind::MethodCall(_, [rargs_self, ..], _) = &rhs.kind; + if let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind; + if let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind; then { span_lint_and_sugg( cx, @@ -711,16 +712,16 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { return; } - if let ExprKind::MethodCall(path, args, _) = &expr.kind { - let recv_ty = cx.typeck_results().expr_ty(&args[0]); + if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind { + let recv_ty = cx.typeck_results().expr_ty(receiver); if recv_ty.is_floating_point() { match path.ident.name.as_str() { - "ln" => check_ln1p(cx, expr, args), - "log" => check_log_base(cx, expr, args), - "powf" => check_powf(cx, expr, args), - "powi" => check_powi(cx, expr, args), - "sqrt" => check_hypot(cx, expr, args), + "ln" => check_ln1p(cx, expr, receiver), + "log" => check_log_base(cx, expr, receiver, args), + "powf" => check_powf(cx, expr, receiver, args), + "powi" => check_powi(cx, expr, receiver, args), + "sqrt" => check_hypot(cx, expr, receiver), _ => {}, } } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 9fb9fd99748b4..97024be16fa47 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -126,7 +126,7 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) { if_chain! { if !value.span.from_expansion(); - if let ExprKind::MethodCall(_, [receiver], _) = value.kind; + if let ExprKind::MethodCall(_, receiver, [], _) = value.kind; if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id); if is_diag_trait_item(cx, method_def_id, sym::ToString); let receiver_ty = cx.typeck_results().expr_ty(receiver); diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index d8bc0bf08f2b3..b628fd9f75814 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl { fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { // Get the hir_id of the object we are calling the method on - if let ExprKind::MethodCall(path, [ref self_arg, ..], _) = expr.kind; + if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind; // Is the method to_string() ? if path.ident.name == sym::to_string; // Is the method a part of the ToString trait? (i.e. not to_string() implemented diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index ebf5ab086dcea..9b9f1872bfc1d 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -54,7 +54,7 @@ fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { impl<'tcx> LateLintPass<'tcx> for FormatPushString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let arg = match expr.kind { - ExprKind::MethodCall(_, [_, arg], _) => { + ExprKind::MethodCall(_, _, [arg], _) => { if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && match_def_path(cx, fn_def_id, &paths::PUSH_STR) { arg diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 6672a6cb0b58f..00a4937763eb5 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { return; } match expr.kind { - Call(_, args) | MethodCall(_, args, _) => { + Call(_, args) => { let mut tys = DefIdSet::default(); for arg in args { if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) @@ -230,6 +230,24 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { tys.clear(); } }, + MethodCall(_, receiver, args, _) => { + let mut tys = DefIdSet::default(); + for arg in std::iter::once(receiver).chain(args.iter()) { + if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) + && is_mutable_ty( + self.cx, + self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + arg.span, + &mut tys, + ) + && is_mutated_static(arg) + { + self.mutates_static = true; + return; + } + tys.clear(); + } + }, Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => { self.mutates_static |= is_mutated_static(target); }, @@ -254,6 +272,6 @@ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bo cx, mutates_static: false, }; - intravisit::walk_expr(&mut v, &body.value); + intravisit::walk_expr(&mut v, body.value); v.mutates_static } diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 565a1c871d758..3bbfa52e81039 100644 --- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -88,11 +88,12 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } } }, - hir::ExprKind::MethodCall(_, args, _) => { + hir::ExprKind::MethodCall(_, receiver, args, _) => { let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap(); let base_type = self.cx.tcx.type_of(def_id); if type_is_unsafe_function(self.cx, base_type) { + self.check_arg(receiver); for arg in args { self.check_arg(arg); } diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index 4d703d691acc2..9ea8c494cfcda 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -129,7 +129,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind; + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; if path.ident.as_str() == "lock"; let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); if is_type_diagnostic_item(cx, ty, sym::Mutex); diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index a6610ade37e56..feec8ec2e23f8 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -232,7 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { return; } - let res_ty = cx.typeck_results().expr_ty(&body.value); + let res_ty = cx.typeck_results().expr_ty(body.value); if res_ty.is_unit() || res_ty.is_never() { return; } @@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { None => return, } } else { - &body.value + body.value }; lint_implicit_returns(cx, expr, expr.span.ctxt(), None); } diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index d0c6495e35a72..0dd7f5bf000d2 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -95,12 +95,14 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap = FxHashSet::default(); let mut slices: FxIndexMap = FxIndexMap::default(); pat.walk_always(|pat| { - if let hir::PatKind::Binding(binding, value_hir_id, ident, sub_pat) = pat.kind { - // We'll just ignore mut and ref mut for simplicity sake right now - if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding { - return; - } - + // We'll just ignore mut and ref mut for simplicity sake right now + if let hir::PatKind::Binding( + hir::BindingAnnotation(by_ref, hir::Mutability::Not), + value_hir_id, + ident, + sub_pat, + ) = pat.kind + { // This block catches bindings with sub patterns. It would be hard to build a correct suggestion // for them and it's likely that the user knows what they are doing in such a case. if removed_pat.contains(&value_hir_id) { @@ -116,7 +118,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap, expr: &Expr<'_>) -> Finiteness { match expr.kind { - ExprKind::MethodCall(method, args, _) => { + ExprKind::MethodCall(method, receiver, args, _) => { for &(name, len, heuristic, cap) in &HEURISTICS { if method.ident.name.as_str() == name && args.len() == len { return (match heuristic { Always => Infinite, - First => is_infinite(cx, &args[0]), - Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), - All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), + First => is_infinite(cx, receiver), + Any => is_infinite(cx, receiver).or(is_infinite(cx, &args[0])), + All => is_infinite(cx, receiver).and(is_infinite(cx, &args[0])), }) .and(cap); } } - if method.ident.name == sym!(flat_map) && args.len() == 2 { - if let ExprKind::Closure(&Closure { body, .. }) = args[1].kind { + if method.ident.name == sym!(flat_map) && args.len() == 1 { + if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind { let body = cx.tcx.hir().body(body); - return is_infinite(cx, &body.value); + return is_infinite(cx, body.value); } } Finite @@ -179,29 +179,29 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { /// the names and argument lengths of methods that *may* exhaust their /// iterators const POSSIBLY_COMPLETING_METHODS: [(&str, usize); 6] = [ - ("find", 2), - ("rfind", 2), - ("position", 2), - ("rposition", 2), - ("any", 2), - ("all", 2), + ("find", 1), + ("rfind", 1), + ("position", 1), + ("rposition", 1), + ("any", 1), + ("all", 1), ]; /// the names and argument lengths of methods that *always* exhaust /// their iterators const COMPLETING_METHODS: [(&str, usize); 12] = [ - ("count", 1), - ("fold", 3), - ("for_each", 2), - ("partition", 2), - ("max", 1), - ("max_by", 2), - ("max_by_key", 2), - ("min", 1), - ("min_by", 2), - ("min_by_key", 2), - ("sum", 1), - ("product", 1), + ("count", 0), + ("fold", 2), + ("for_each", 1), + ("partition", 1), + ("max", 0), + ("max_by", 1), + ("max_by_key", 1), + ("min", 0), + ("min_by", 1), + ("min_by_key", 1), + ("sum", 0), + ("product", 0), ]; /// the paths of types that are known to be infinitely allocating @@ -218,26 +218,26 @@ const INFINITE_COLLECTORS: &[Symbol] = &[ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { - ExprKind::MethodCall(method, args, _) => { + ExprKind::MethodCall(method, receiver, args, _) => { for &(name, len) in &COMPLETING_METHODS { if method.ident.name.as_str() == name && args.len() == len { - return is_infinite(cx, &args[0]); + return is_infinite(cx, receiver); } } for &(name, len) in &POSSIBLY_COMPLETING_METHODS { if method.ident.name.as_str() == name && args.len() == len { - return MaybeInfinite.and(is_infinite(cx, &args[0])); + return MaybeInfinite.and(is_infinite(cx, receiver)); } } - if method.ident.name == sym!(last) && args.len() == 1 { + if method.ident.name == sym!(last) && args.is_empty() { let not_double_ended = cx .tcx .get_diagnostic_item(sym::DoubleEndedIterator) .map_or(false, |id| { - !implements_trait(cx, cx.typeck_results().expr_ty(&args[0]), id, &[]) + !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[]) }); if not_double_ended { - return is_infinite(cx, &args[0]); + return is_infinite(cx, receiver); } } else if method.ident.name == sym!(collect) { let ty = cx.typeck_results().expr_ty(expr); @@ -245,7 +245,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { .iter() .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item)) { - return is_infinite(cx, &args[0]); + return is_infinite(cx, receiver); } } }, diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 246f5aad8fbad..7ae8ef830faea 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -370,7 +370,8 @@ fn check_for_is_empty<'tcx>( } fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { - if let (&ExprKind::MethodCall(method_path, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { + if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) + { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { if name.as_str() == "is_empty" { @@ -378,16 +379,28 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_> } } - check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to); + check_len( + cx, + span, + method_path.ident.name, + receiver, + args, + &lit.node, + op, + compare_to, + ); } else { check_empty_expr(cx, span, method, lit, op); } } +// FIXME(flip1995): Figure out how to reduce the number of arguments +#[allow(clippy::too_many_arguments)] fn check_len( cx: &LateContext<'_>, span: Span, method_name: Symbol, + receiver: &Expr<'_>, args: &[Expr<'_>], lit: &LitKind, op: &str, @@ -399,7 +412,7 @@ fn check_len( return; } - if method_name == sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) { + if method_name == sym::len && args.is_empty() && has_is_empty(cx, receiver) { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, @@ -410,7 +423,7 @@ fn check_len( format!( "{}{}.is_empty()", op, - snippet_with_applicability(cx, args[0].span, "_", &mut applicability) + snippet_with_applicability(cx, receiver.span, "_", &mut applicability) ), applicability, ); diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 56bbbbbc819e5..10fc0f4018efd 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -4,7 +4,7 @@ use clippy_utils::{path_to_local_id, visitors::is_local_used}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::BindingAnnotation; +use rustc_hir::{BindingAnnotation, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { }; let mutability = match mode { - BindingAnnotation::RefMut | BindingAnnotation::Mutable => " ", + BindingAnnotation(_, Mutability::Mut) => " ", _ => "", }; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7633bf347c3d5..ec96999896e28 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -4,6 +4,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(iter_intersperse)] +#![feature(let_chains)] #![feature(let_else)] #![feature(lint_reasons)] #![feature(never_type)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 573a7c016b8e8..d9cf92a9d5ba1 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -276,7 +276,7 @@ fn could_use_elision<'tcx>( let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false, }; - checker.visit_expr(&body.value); + checker.visit_expr(body.value); if checker.lifetimes_used_in_body { return false; } diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs index 215c83a7edf6e..09b2376d5c04a 100644 --- a/clippy_lints/src/loops/manual_find.rs +++ b/clippy_lints/src/loops/manual_find.rs @@ -106,7 +106,7 @@ fn get_binding(pat: &Pat<'_>) -> Option { hir_id = None; return; } - if let BindingAnnotation::Unannotated = annotation { + if let BindingAnnotation::NONE = annotation { hir_id = Some(id); } }); diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index a65df48e413e8..3fc569af89ecb 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -119,7 +119,7 @@ fn build_manual_memcpy_suggestion<'tcx>( let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| { if_chain! { - if let ExprKind::MethodCall(method, [recv], _) = end.kind; + if let ExprKind::MethodCall(method, recv, [], _) = end.kind; if method.ident.name == sym::len; if path_to_local(recv) == path_to_local(base); then { @@ -341,7 +341,7 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { if_chain! { - if let ExprKind::MethodCall(method, [arg], _) = expr.kind; + if let ExprKind::MethodCall(method, arg, [], _) = expr.kind; if method.ident.name == sym::clone; then { arg } else { expr } } diff --git a/clippy_lints/src/loops/missing_spin_loop.rs b/clippy_lints/src/loops/missing_spin_loop.rs index 0696afa39225f..8412875b11b7e 100644 --- a/clippy_lints/src/loops/missing_spin_loop.rs +++ b/clippy_lints/src/loops/missing_spin_loop.rs @@ -33,7 +33,7 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind; - if let ExprKind::MethodCall(method, [callee, ..], _) = unpack_cond(cond).kind; + if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind; if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name); if let ty::Adt(def, _substs) = cx.typeck_results().expr_ty(callee).kind(); if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did()); diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index ed270bd490d78..74f3bda9f43ef 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -742,7 +742,7 @@ fn check_for_loop<'tcx>( fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used - if let ExprKind::MethodCall(method, [self_arg], _) = arg.kind { + if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { let method_name = method.ident.as_str(); // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x match method_name { diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index aedf3810b23e9..fce2d54639cbf 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -44,7 +44,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option if_chain! { if let Some(hir_id) = path_to_local(bound); if let Node::Pat(pat) = cx.tcx.hir().get(hir_id); - if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind; + if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind; then { return Some(hir_id); } diff --git a/clippy_lints/src/loops/needless_collect.rs b/clippy_lints/src/loops/needless_collect.rs index 6d987f393fa5c..6e6faa79adc9e 100644 --- a/clippy_lints/src/loops/needless_collect.rs +++ b/clippy_lints/src/loops/needless_collect.rs @@ -25,11 +25,11 @@ pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { } fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if_chain! { - if let ExprKind::MethodCall(method, args, _) = expr.kind; - if let ExprKind::MethodCall(chain_method, _, _) = args[0].kind; - if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator); + if let ExprKind::MethodCall(method, receiver, args, _) = expr.kind; + if let ExprKind::MethodCall(chain_method, ..) = receiver.kind; + if chain_method.ident.name == sym!(collect) && is_trait_method(cx, receiver, sym::Iterator); then { - let ty = cx.typeck_results().expr_ty(&args[0]); + let ty = cx.typeck_results().expr_ty(receiver); let mut applicability = Applicability::MaybeIncorrect; let is_empty_sugg = "next().is_none()".to_string(); let method_name = method.ident.name.as_str(); @@ -41,7 +41,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont "len" => "count()".to_string(), "is_empty" => is_empty_sugg, "contains" => { - let contains_arg = snippet_with_applicability(cx, args[1].span, "??", &mut applicability); + let contains_arg = snippet_with_applicability(cx, args[0].span, "??", &mut applicability); let (arg, pred) = contains_arg .strip_prefix('&') .map_or(("&x", &*contains_arg), |s| ("x", s)); @@ -80,7 +80,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo if let StmtKind::Local(local) = stmt.kind; if let PatKind::Binding(_, id, ..) = local.pat.kind; if let Some(init_expr) = local.init; - if let ExprKind::MethodCall(method_name, &[ref iter_source], ..) = init_expr.kind; + if let ExprKind::MethodCall(method_name, iter_source, [], ..) = init_expr.kind; if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator); let ty = cx.typeck_results().expr_ty(init_expr); if is_type_diagnostic_item(cx, ty, sym::Vec) || @@ -203,7 +203,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection - if let ExprKind::MethodCall(method_name, [recv, args @ ..], _) = &expr.kind { + if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind { if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) { self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv)); self.visit_expr(recv); diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index 7ca4a7c4ebfc2..8ab640051b635 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -188,7 +188,7 @@ pub(super) fn check<'tcx>( fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { if_chain! { - if let ExprKind::MethodCall(method, [recv], _) = expr.kind; + if let ExprKind::MethodCall(method, recv, [], _) = expr.kind; if method.ident.name == sym::len; if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind; if path.segments.len() == 1; @@ -301,7 +301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if_chain! { // a range index op - if let ExprKind::MethodCall(meth, [args_0, args_1, ..], _) = &expr.kind; + if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind; if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX)) || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); if !self.check(args_1, args_0, expr); @@ -356,9 +356,12 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { self.visit_expr(expr); } }, - ExprKind::MethodCall(_, args, _) => { + ExprKind::MethodCall(_, receiver, args, _) => { let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); - for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) { + for (ty, expr) in iter::zip( + self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), + std::iter::once(receiver).chain(args.iter()), + ) { self.prefer_mutable = false; if let ty::Ref(_, _, mutbl) = *ty.kind() { if mutbl == Mutability::Mut { @@ -370,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { }, ExprKind::Closure(&Closure { body, .. }) => { let body = self.cx.tcx.hir().body(body); - self.visit_expr(&body.value); + self.visit_expr(body.value); }, _ => walk_expr(self, expr), } diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 32de20f6531fe..116e589cad6f3 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -120,8 +120,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { | ExprKind::Repeat(e, _) | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id), ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id), - ExprKind::Array(es) | ExprKind::MethodCall(_, es, _) | ExprKind::Tup(es) => { - never_loop_expr_all(&mut es.iter(), main_loop_id) + ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), main_loop_id), + ExprKind::MethodCall(_, receiver, es, _) => { + never_loop_expr_all(&mut std::iter::once(receiver).chain(es.iter()), main_loop_id) }, ExprKind::Struct(_, fields, base) => { let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), main_loop_id); @@ -178,9 +179,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { never_loop_expr(expr, main_loop_id) }, - InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id), + InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter().copied(), main_loop_id), InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { - never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id) + never_loop_expr_all(&mut once(*in_expr).chain(out_expr.iter().copied()), main_loop_id) }, InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 1439f1f4c75d5..aeefe6e33fbe9 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -7,7 +7,7 @@ use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind}; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; use std::iter::Iterator; @@ -65,7 +65,7 @@ pub(super) fn check<'tcx>( if_chain! { if let Node::Pat(pat) = node; if let PatKind::Binding(bind_ann, ..) = pat.kind; - if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable); + if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)); let parent_node = cx.tcx.hir().get_parent_node(hir_id); if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node); if let Some(init) = parent_let_expr.init; @@ -180,10 +180,9 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(& if_chain! { // Extract method being called if let StmtKind::Semi(semi_stmt) = &stmt.kind; - if let ExprKind::MethodCall(path, args, _) = &semi_stmt.kind; + if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind; // Figure out the parameters for the method call - if let Some(self_expr) = args.get(0); - if let Some(pushed_item) = args.get(1); + if let Some(pushed_item) = args.get(0); // Check that the method being called is push() on a Vec if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec); if path.ident.name.as_str() == "push"; diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index a0bd7ad0ac647..f4b47808dfaa3 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -35,32 +35,29 @@ pub(super) fn check<'tcx>( ) => (arg, "&mut "), ExprKind::MethodCall( method, - [ - Expr { - kind: ExprKind::Array([arg]), - .. - }, - ], + Expr { + kind: ExprKind::Array([arg]), + .. + }, + [], _, ) if method.ident.name == rustc_span::sym::iter => (arg, "&"), ExprKind::MethodCall( method, - [ - Expr { - kind: ExprKind::Array([arg]), - .. - }, - ], + Expr { + kind: ExprKind::Array([arg]), + .. + }, + [], _, ) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "), ExprKind::MethodCall( method, - [ - Expr { - kind: ExprKind::Array([arg]), - .. - }, - ], + Expr { + kind: ExprKind::Array([arg]), + .. + }, + [], _, ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""), // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise. diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index 45af6be2653f3..735d704a43cee 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -11,7 +11,14 @@ use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { ([stmt, stmts @ ..], expr) => { - if let StmtKind::Local(&Local { init: Some(e), .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind { + if let StmtKind::Local(&Local { + init: Some(e), + els: None, + .. + }) + | StmtKind::Semi(e) + | StmtKind::Expr(e) = stmt.kind + { (e, !stmts.is_empty() || expr.is_some()) } else { return; diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index e9e215e662f19..deb21894f36a9 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Res::Def(_, pat_did) = pat_path.res; if match_def_path(cx, pat_did, &paths::OPTION_SOME); // check for call to `Iterator::next` - if let ExprKind::MethodCall(method_name, [iter_expr], _) = let_expr.kind; + if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind; if method_name.ident.name == sym::next; if is_trait_method(cx, let_expr, sym::Iterator); if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr); @@ -356,7 +356,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: & after_loop: false, used_iter: false, }; - v.visit_expr(&cx.tcx.hir().body(cx.enclosing_body.unwrap()).value); + v.visit_expr(cx.tcx.hir().body(cx.enclosing_body.unwrap()).value); v.used_iter } } diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 60bbcde4f1de5..6655c92b1da8d 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -105,7 +105,7 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option< if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id(); if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id); then { - cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (real_ty, resolved_ty)) + cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty)) } else { None } @@ -134,7 +134,7 @@ fn create_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, base_sugg: String) -> Stri fn is_ty_conversion(expr: &Expr<'_>) -> bool { if let ExprKind::Cast(..) = expr.kind { true - } else if let ExprKind::MethodCall(path, [_], _) = expr.kind + } else if let ExprKind::MethodCall(path, _, [], _) = expr.kind && path.ident.name == rustc_span::sym::try_into { // This is only called for `usize` which implements `TryInto`. Therefore, diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 42d2577cc3161..f28c37d3dca7e 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -66,9 +66,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if let Some(parent_expr) = get_parent_expr(cx, expr) && let Assign(left_expr, collect_expr, _) = &parent_expr.kind - && let hir::ExprKind::MethodCall(seg, _, _) = &collect_expr.kind + && let hir::ExprKind::MethodCall(seg, ..) = &collect_expr.kind && seg.args.is_none() - && let hir::ExprKind::MethodCall(_, [target_expr], _) = &collect_expr.kind + && let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id) && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) { check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv); @@ -87,10 +87,10 @@ fn check_into_iter( target_expr: &hir::Expr<'_>, msrv: Option, ) { - if let hir::ExprKind::MethodCall(_, [into_iter_expr, _], _) = &target_expr.kind + if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) - && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &into_iter_expr.kind + && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id) && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER) && match_acceptable_type(cx, left_expr, msrv) @@ -106,14 +106,14 @@ fn check_iter( target_expr: &hir::Expr<'_>, msrv: Option, ) { - if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind + if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED) || match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED)) - && let hir::ExprKind::MethodCall(_, [iter_expr, _], _) = &filter_expr.kind + && let hir::ExprKind::MethodCall(_, iter_expr, [_], _) = &filter_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) - && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &iter_expr.kind + && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &iter_expr.kind && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id) && match_acceptable_def_path(cx, iter_expr_def_id) && match_acceptable_type(cx, left_expr, msrv) @@ -130,13 +130,13 @@ fn check_to_owned( msrv: Option, ) { if meets_msrv(msrv, msrvs::STRING_RETAIN) - && let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind + && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD) - && let hir::ExprKind::MethodCall(_, [chars_expr, _], _) = &filter_expr.kind + && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) - && let hir::ExprKind::MethodCall(_, [str_expr], _) = &chars_expr.kind + && let hir::ExprKind::MethodCall(_, str_expr, [], _) = &chars_expr.kind && let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id) && match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS) && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs() @@ -147,7 +147,7 @@ fn check_to_owned( } fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) { - if let hir::ExprKind::MethodCall(_, [_, closure], _) = filter_expr.kind + if let hir::ExprKind::MethodCall(_, _, [closure], _) = filter_expr.kind && let hir::ExprKind::Closure(&hir::Closure { body, ..}) = closure.kind && let filter_body = cx.tcx.hir().body(body) && let [filter_params] = filter_body.params diff --git a/clippy_lints/src/manual_string_new.rs b/clippy_lints/src/manual_string_new.rs index a90eaa8fdcbe3..6acfb2ae3471c 100644 --- a/clippy_lints/src/manual_string_new.rs +++ b/clippy_lints/src/manual_string_new.rs @@ -55,8 +55,8 @@ impl LateLintPass<'_> for ManualStringNew { ExprKind::Call(func, args) => { parse_call(cx, expr.span, func, args); }, - ExprKind::MethodCall(path_segment, args, _) => { - parse_method_call(cx, expr.span, path_segment, args); + ExprKind::MethodCall(path_segment, receiver, ..) => { + parse_method_call(cx, expr.span, path_segment, receiver); }, _ => (), } @@ -88,14 +88,9 @@ fn warn_then_suggest(cx: &LateContext<'_>, span: Span) { } /// Tries to parse an expression as a method call, emitting the warning if necessary. -fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, args: &[Expr<'_>]) { - if args.is_empty() { - // When parsing TryFrom::try_from(...).expect(...), we will have more than 1 arg. - return; - } - +fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, receiver: &Expr<'_>) { let ident = path_segment.ident.as_str(); - let method_arg_kind = &args[0].kind; + let method_arg_kind = &receiver.kind; if ["to_string", "to_owned", "into"].contains(&ident) && is_expr_kind_empty_str(method_arg_kind) { warn_then_suggest(cx, span); } else if let ExprKind::Call(func, args) = method_arg_kind { diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index dfb3efc4e28b6..7941c8c9c7e39 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { if_chain! { if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr); - if let ExprKind::MethodCall(_, [target_arg, pattern], _) = cond.kind; + if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind; if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id); if let ExprKind::Path(target_path) = &target_arg.kind; then { @@ -132,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise. fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::MethodCall(_, [arg], _) = expr.kind; + if let ExprKind::MethodCall(_, arg, [], _) = expr.kind; if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if match_def_path(cx, method_def_id, &paths::STR_LEN); then { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 6db852c3ffe79..33d744815299f 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -200,8 +200,13 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { ) } -fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { - let var_arg = &map_args[0]; +fn lint_map_unit_fn( + cx: &LateContext<'_>, + stmt: &hir::Stmt<'_>, + expr: &hir::Expr<'_>, + map_args: (&hir::Expr<'_>, &[hir::Expr<'_>]), +) { + let var_arg = &map_args.0; let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) { ("Option", "Some", OPTION_MAP_UNIT_FN) @@ -210,7 +215,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr } else { return; }; - let fn_arg = &map_args[1]; + let fn_arg = &map_args.1[0]; if is_unit_function(cx, fn_arg) { let mut applicability = Applicability::MachineApplicable; diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs index 3349b85f1347a..8588ab1ed8db7 100644 --- a/clippy_lints/src/match_result_ok.rs +++ b/clippy_lints/src/match_result_ok.rs @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk { }; if_chain! { - if let ExprKind::MethodCall(ok_path, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result.ok(, _) + if let ExprKind::MethodCall(ok_path, result_types_0, ..) = let_expr.kind; //check is expr.ok() has type Result.ok(, _) if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _) = let_pat.kind; //get operation if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() method use std::marker::Sized; if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::Result); diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs index 8f98b43b9e5c8..b0198e856d5b6 100644 --- a/clippy_lints/src/matches/manual_map.rs +++ b/clippy_lints/src/matches/manual_map.rs @@ -165,7 +165,7 @@ fn check<'tcx>( } // `ref` and `ref mut` annotations were handled earlier. - let annotation = if matches!(annotation, BindingAnnotation::Mutable) { + let annotation = if matches!(annotation, BindingAnnotation::MUT) { "mut " } else { "" diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs index a0efdecec67f4..91d17f481e2df 100644 --- a/clippy_lints/src/matches/match_as_ref.rs +++ b/clippy_lints/src/matches/match_as_ref.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_lang_ctor, peel_blocks}; use rustc_errors::Applicability; -use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, LangItem, PatKind, QPath}; +use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty; @@ -10,18 +10,17 @@ use super::MATCH_AS_REF; pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { - let arm_ref: Option = if is_none_arm(cx, &arms[0]) { + let arm_ref_mut = if is_none_arm(cx, &arms[0]) { is_ref_some_arm(cx, &arms[1]) } else if is_none_arm(cx, &arms[1]) { is_ref_some_arm(cx, &arms[0]) } else { None }; - if let Some(rb) = arm_ref { - let suggestion = if rb == BindingAnnotation::Ref { - "as_ref" - } else { - "as_mut" + if let Some(rb) = arm_ref_mut { + let suggestion = match rb { + Mutability::Not => "as_ref", + Mutability::Mut => "as_mut", }; let output_ty = cx.typeck_results().expr_ty(expr); @@ -66,19 +65,18 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { } // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) -fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option { +fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option { if_chain! { if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind; if is_lang_ctor(cx, qpath, LangItem::OptionSome); - if let PatKind::Binding(rb, .., ident, _) = first_pat.kind; - if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; + if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind; if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind; if let ExprKind::Path(ref some_path) = e.kind; if is_lang_ctor(cx, some_path, LangItem::OptionSome); if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind; if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; then { - return Some(rb) + return Some(mutabl) } } None diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs index fa3b8d1fceaac..1e80b6cf2d838 100644 --- a/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -48,7 +48,7 @@ struct MatchExprVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { match ex.kind { - ExprKind::MethodCall(segment, [receiver], _) if self.case_altered(segment.ident.as_str(), receiver) => {}, + ExprKind::MethodCall(segment, receiver, [], _) if self.case_altered(segment.ident.as_str(), receiver) => {}, _ => walk_expr(self, ex), } } diff --git a/clippy_lints/src/matches/needless_match.rs b/clippy_lints/src/matches/needless_match.rs index 6f037339ec758..634eef82e532a 100644 --- a/clippy_lints/src/matches/needless_match.rs +++ b/clippy_lints/src/matches/needless_match.rs @@ -8,7 +8,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath}; +use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_span::sym; use rustc_typeck::hir_ty_to_ty; @@ -189,8 +189,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { }, )), ) => { - return !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut) - && pat_ident.name == first_seg.ident.name; + return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name; }, // Example: `Custom::TypeA => Custom::TypeB`, or `None => None` (PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => { diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index 8499e050af242..f7443471e31dd 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -120,7 +120,7 @@ fn find_sugg_for_if_let<'tcx>( // check that `while_let_on_iterator` lint does not trigger if_chain! { if keyword == "while"; - if let ExprKind::MethodCall(method_path, _, _) = let_expr.kind; + if let ExprKind::MethodCall(method_path, ..) = let_expr.kind; if method_path.ident.name == sym::next; if is_trait_method(cx, let_expr, sym::Iterator); then { diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index b0b15b3f54cd8..86a9df034979b 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -291,7 +291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { self.is_chain_end = false; match ex.kind { - ExprKind::MethodCall(_, [ref expr, ..], _) => { + ExprKind::MethodCall(_, expr, ..) => { self.visit_expr(expr); } ExprKind::Binary(_, left, right) => { @@ -331,8 +331,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { ExprKind::Index(..) | ExprKind::Ret(..) | ExprKind::Repeat(..) | - ExprKind::Yield(..) | - ExprKind::MethodCall(..) => walk_expr(self, ex), + ExprKind::Yield(..) => walk_expr(self, ex), ExprKind::AddrOf(_, _, _) | ExprKind::Block(_, _) | ExprKind::Break(_, _) | diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 52632e88b1bd9..38df69eeb379b 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -175,7 +175,7 @@ fn collect_pat_paths<'a>(acc: &mut Vec>, cx: &LateContext<'a>, pat: &Pat< let p_ty = cx.typeck_results().pat_ty(p); collect_pat_paths(acc, cx, p, p_ty); }), - PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::Unannotated, .., None) | PatKind::Path(_) => { + PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::NONE, .., None) | PatKind::Path(_) => { acc.push(ty); }, _ => {}, diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 2f117e4dcc374..22f5635a5bccb 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -152,7 +152,7 @@ pub(crate) trait BindInsteadOfMap { match arg.kind { hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) => { let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(&closure_body.value); + let closure_expr = peel_blocks(closure_body.value); if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) { true diff --git a/clippy_lints/src/methods/bytecount.rs b/clippy_lints/src/methods/bytecount.rs index 6a7c63d76f72c..fef90f6eba495 100644 --- a/clippy_lints/src/methods/bytecount.rs +++ b/clippy_lints/src/methods/bytecount.rs @@ -42,11 +42,11 @@ pub(super) fn check<'tcx>( if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); if !is_local_used(cx, needle, arg_id); then { - let haystack = if let ExprKind::MethodCall(path, args, _) = + let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = filter_recv.kind { let p = path.ident.name; - if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 { - &args[0] + if p == sym::iter || p == sym!(iter_mut) { + receiver } else { filter_recv } diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs index f7b79f0839ba8..b2bc1ad5c9ed0 100644 --- a/clippy_lints/src/methods/chars_cmp.rs +++ b/clippy_lints/src/methods/chars_cmp.rs @@ -23,7 +23,7 @@ pub(super) fn check( if Some(id) == cx.tcx.lang_items().option_some_variant(); then { let mut applicability = Applicability::MachineApplicable; - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs(); + let self_ty = cx.typeck_results().expr_ty_adjusted(args[0].0).peel_refs(); if *self_ty.kind() != ty::Str { return false; @@ -37,7 +37,7 @@ pub(super) fn check( "like this", format!("{}{}.{}({})", if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), suggest, snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)), applicability, diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs index a7c0e43923e13..b85bfec2b12ba 100644 --- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs +++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -30,7 +30,7 @@ pub(super) fn check<'tcx>( "like this", format!("{}{}.{}('{}')", if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), suggest, c.escape_default()), applicability, diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 60e1355f9b92d..7ab6b84c20749 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::sugg; use clippy_utils::ty::is_copy; use rustc_errors::Applicability; -use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; +use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty::{self, adjustment::Adjust}; use rustc_span::symbol::{sym, Symbol}; @@ -14,10 +14,17 @@ use super::CLONE_ON_COPY; /// Checks for the `CLONE_ON_COPY` lint. #[allow(clippy::too_many_lines)] -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, args: &[Expr<'_>]) { - let arg = match args { - [arg] if method_name == sym::clone => arg, - _ => return, +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + method_name: Symbol, + receiver: &Expr<'_>, + args: &[Expr<'_>], +) { + let arg = if method_name == sym::clone && args.is_empty() { + receiver + } else { + return; }; if cx .typeck_results() @@ -81,7 +88,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, // &*x is a nop, &x.clone() is not ExprKind::AddrOf(..) => return, // (*x).func() is useless, x.clone().func() can work in case func borrows self - ExprKind::MethodCall(_, [self_arg, ..], _) + ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) => { return; @@ -91,19 +98,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, hir_callee.kind, ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _)) ), - ExprKind::MethodCall(_, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true, + ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true, ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) | ExprKind::Field(..) | ExprKind::Index(..) => true, _ => false, }, // local binding capturing a reference - Some(Node::Local(l)) - if matches!( - l.pat.kind, - PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) - ) => - { + Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => { return; }, _ => false, diff --git a/clippy_lints/src/methods/clone_on_ref_ptr.rs b/clippy_lints/src/methods/clone_on_ref_ptr.rs index 6417bc8130473..f82ca89120061 100644 --- a/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -10,12 +10,17 @@ use rustc_span::symbol::{sym, Symbol}; use super::CLONE_ON_REF_PTR; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { - if !(args.len() == 1 && method_name == sym::clone) { +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + method_name: Symbol, + receiver: &hir::Expr<'_>, + args: &[hir::Expr<'_>], +) { + if !(args.is_empty() && method_name == sym::clone) { return; } - let arg = &args[0]; - let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs(); + let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); if let ty::Adt(_, subst) = obj_ty.kind() { let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) { @@ -28,7 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Sym return; }; - let snippet = snippet_with_macro_callsite(cx, arg.span, ".."); + let snippet = snippet_with_macro_callsite(cx, receiver.span, ".."); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/methods/collapsible_str_replace.rs b/clippy_lints/src/methods/collapsible_str_replace.rs index 561033be5b6af..501646863fe15 100644 --- a/clippy_lints/src/methods/collapsible_str_replace.rs +++ b/clippy_lints/src/methods/collapsible_str_replace.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>( // If the parent node's `to` argument is the same as the `to` argument // of the last replace call in the current chain, don't lint as it was already linted if let Some(parent) = get_parent_expr(cx, expr) - && let Some(("replace", [_, current_from, current_to], _)) = method_call(parent) + && let Some(("replace", _, [current_from, current_to], _)) = method_call(parent) && eq_expr_value(cx, to, current_to) && from_kind == cx.typeck_results().expr_ty(current_from).peel_refs().kind() { @@ -48,7 +48,7 @@ fn collect_replace_calls<'tcx>( let mut from_args = VecDeque::new(); let _: Option<()> = for_each_expr(expr, |e| { - if let Some(("replace", [_, from, to], _)) = method_call(e) { + if let Some(("replace", _, [from, to], _)) = method_call(e) { if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() { methods.push_front(e); from_args.push_front(from); @@ -78,7 +78,7 @@ fn check_consecutive_replace_calls<'tcx>( .collect(); let app = Applicability::MachineApplicable; let earliest_replace_call = replace_methods.methods.front().unwrap(); - if let Some((_, [..], span_lo)) = method_call(earliest_replace_call) { + if let Some((_, _, [..], span_lo)) = method_call(earliest_replace_call) { span_lint_and_sugg( cx, COLLAPSIBLE_STR_REPLACE, diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index 6f2307d8f18ff..bd846d71d4668 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -19,6 +19,7 @@ pub(super) fn check<'tcx>( expr: &hir::Expr<'_>, method_span: Span, name: &str, + receiver: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], ) { // Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or @@ -28,16 +29,13 @@ pub(super) fn check<'tcx>( loop { arg_root = match &arg_root.kind { hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr, - hir::ExprKind::MethodCall(method_name, call_args, _) => { - if call_args.len() == 1 - && (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) - && { - let arg_type = cx.typeck_results().expr_ty(&call_args[0]); - let base_type = arg_type.peel_refs(); - *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String) - } - { - &call_args[0] + hir::ExprKind::MethodCall(method_name, receiver, [], ..) => { + if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && { + let arg_type = cx.typeck_results().expr_ty(receiver); + let base_type = arg_type.peel_refs(); + *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String) + } { + receiver } else { break; } @@ -114,11 +112,11 @@ pub(super) fn check<'tcx>( } } - if args.len() != 2 || name != "expect" || !is_call(&args[1].kind) { + if args.len() != 1 || name != "expect" || !is_call(&args[0].kind) { return; } - let receiver_type = cx.typeck_results().expr_ty_adjusted(&args[0]); + let receiver_type = cx.typeck_results().expr_ty_adjusted(receiver); let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::Option) { "||" } else if is_type_diagnostic_item(cx, receiver_type, sym::Result) { @@ -127,7 +125,7 @@ pub(super) fn check<'tcx>( return; }; - let arg_root = get_arg_root(cx, &args[1]); + let arg_root = get_arg_root(cx, &args[0]); let span_replace_word = method_span.with_hi(expr.span.hi()); diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index a15fe60940225..37b28463527cc 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: if_chain! { if is_type_diagnostic_item(cx, ty, sym::Vec); //check source object - if let ExprKind::MethodCall(src_method, [drain_vec, drain_arg], _) = &arg.kind; + if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind; if src_method.ident.as_str() == "drain"; let src_ty = cx.typeck_results().expr_ty(drain_vec); //check if actual src type is mutable for code suggestion diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 692e22a7c5cf7..9719b2f1c5125 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -25,14 +25,14 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy }, hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(&body.value); + let closure_expr = peel_blocks(body.value); let arg_id = body.params[0].pat.hir_id; match closure_expr.kind { - hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, args, _) => { + hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { if_chain! { if ident.name == method_name; - if let hir::ExprKind::Path(path) = &args[0].kind; - if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id); + if let hir::ExprKind::Path(path) = &receiver.kind; + if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id); then { return arg_id == *local } @@ -106,7 +106,7 @@ pub(super) fn check<'tcx>( }; // closure ends with is_some() or is_ok() if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind; - if let ExprKind::MethodCall(path, [filter_arg], _) = filter_body.value.kind; + if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind; if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def(); if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) { Some(false) @@ -123,13 +123,13 @@ pub(super) fn check<'tcx>( if let [map_param] = map_body.params; if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind; // closure ends with expect() or unwrap() - if let ExprKind::MethodCall(seg, [map_arg, ..], _) = map_body.value.kind; + if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind; if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or); // .filter(..).map(|y| f(y).copied().unwrap()) // ~~~~ let map_arg_peeled = match map_arg.kind { - ExprKind::MethodCall(method, [original_arg], _) if acceptable_methods(method) => { + ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => { original_arg }, _ => map_arg, diff --git a/clippy_lints/src/methods/get_last_with_len.rs b/clippy_lints/src/methods/get_last_with_len.rs index 23368238ef5cc..02aada87202c2 100644 --- a/clippy_lints/src/methods/get_last_with_len.rs +++ b/clippy_lints/src/methods/get_last_with_len.rs @@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: ) = arg.kind // LHS of subtraction is "x.len()" - && let ExprKind::MethodCall(lhs_path, [lhs_recv], _) = &lhs.kind + && let ExprKind::MethodCall(lhs_path, lhs_recv, [], _) = &lhs.kind && lhs_path.ident.name == sym::len // RHS of subtraction is 1 diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index f52170df662ca..e1c9b5248a8a4 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -12,13 +12,19 @@ use rustc_span::symbol::{sym, Symbol}; use super::INEFFICIENT_TO_STRING; /// Checks for the `INEFFICIENT_TO_STRING` lint -pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { +pub fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &hir::Expr<'_>, + method_name: Symbol, + receiver: &hir::Expr<'_>, + args: &[hir::Expr<'_>], +) { if_chain! { - if args.len() == 1 && method_name == sym::to_string; + if args.is_empty() && method_name == sym::to_string; if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id); - let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); + let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver); let self_ty = substs.type_at(0); let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty); if deref_count >= 1; @@ -35,7 +41,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy self_ty, deref_self_ty )); let mut applicability = Applicability::MachineApplicable; - let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability); + let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability); diag.span_suggestion( expr.span, "try dereferencing the receiver", diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index da13b4ba37a56..11e76841e9f05 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -16,9 +16,9 @@ pub(super) fn check( expr: &hir::Expr<'_>, method_span: Span, method_name: Symbol, - args: &[hir::Expr<'_>], + receiver: &hir::Expr<'_>, ) { - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); + let self_ty = cx.typeck_results().expr_ty_adjusted(receiver); if_chain! { if let ty::Ref(..) = self_ty.kind(); if method_name == sym::into_iter; diff --git a/clippy_lints/src/methods/iter_skip_next.rs b/clippy_lints/src/methods/iter_skip_next.rs index 43e9451f7d37e..beb772100affc 100644 --- a/clippy_lints/src/methods/iter_skip_next.rs +++ b/clippy_lints/src/methods/iter_skip_next.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr if let Some(id) = path_to_local(recv); if let Node::Pat(pat) = cx.tcx.hir().get(id); if let PatKind::Binding(ann, _, _, _) = pat.kind; - if ann != BindingAnnotation::Mutable; + if ann != BindingAnnotation::MUT; then { application = Applicability::Unspecified; diag.span_help( diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs index 152072e09c772..a669cbbbcc602 100644 --- a/clippy_lints/src/methods/iter_with_drain.rs +++ b/clippy_lints/src/methods/iter_with_drain.rs @@ -35,7 +35,7 @@ fn is_full_range(cx: &LateContext<'_>, container: &Expr<'_>, range: Range<'_>) - && range.end.map_or(true, |e| { if range.limits == RangeLimits::HalfOpen && let ExprKind::Path(QPath::Resolved(None, container_path)) = container.kind - && let ExprKind::MethodCall(name, [self_arg], _) = e.kind + && let ExprKind::MethodCall(name, self_arg, [], _) = e.kind && name.ident.name == sym::len && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind { diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index ffedda95ff8e5..8261ef5e1ce34 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -30,16 +30,16 @@ pub(super) fn check<'tcx>( if let hir::ExprKind::Closure(&hir::Closure{ body, .. }) = arg.kind; then { let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(&closure_body.value); + let closure_expr = peel_blocks(closure_body.value); match closure_body.params[0].pat.kind { hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding( - hir::BindingAnnotation::Unannotated, .., name, None + hir::BindingAnnotation::NONE, .., name, None ) = inner.kind { if ident_eq(name, closure_expr) { lint_explicit_closure(cx, e.span, recv.span, true, msrv); } }, - hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => { + hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => { match closure_expr.kind { hir::ExprKind::Unary(hir::UnOp::Deref, inner) => { if ident_eq(name, inner) { @@ -48,7 +48,7 @@ pub(super) fn check<'tcx>( } } }, - hir::ExprKind::MethodCall(method, [obj], _) => if_chain! { + hir::ExprKind::MethodCall(method, obj, [], _) => if_chain! { if ident_eq(name, obj) && method.ident.name == sym::clone; if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id); if let Some(trait_id) = cx.tcx.trait_of_item(fn_id); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b7d2d980db801..41942b20ea163 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3162,11 +3162,13 @@ impl_lint_pass!(Methods => [ ]); /// Extracts a method call name, args, and `Span` of the method name. -fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx str, &'tcx [hir::Expr<'tcx>], Span)> { - if let ExprKind::MethodCall(path, args, _) = recv.kind { - if !args.iter().any(|e| e.span.from_expansion()) { +fn method_call<'tcx>( + recv: &'tcx hir::Expr<'tcx>, +) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span)> { + if let ExprKind::MethodCall(path, receiver, args, _) = recv.kind { + if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() { let name = path.ident.name.as_str(); - return Some((name, args, path.ident.span)); + return Some((name, receiver, args, path.ident.span)); } } None @@ -3184,17 +3186,17 @@ impl<'tcx> LateLintPass<'tcx> for Methods { hir::ExprKind::Call(func, args) => { from_iter_instead_of_collect::check(cx, expr, args, func); }, - hir::ExprKind::MethodCall(method_call, args, _) => { + hir::ExprKind::MethodCall(method_call, receiver, args, _) => { let method_span = method_call.ident.span; - or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args); - expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args); - clone_on_copy::check(cx, expr, method_call.ident.name, args); - clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args); - inefficient_to_string::check(cx, expr, method_call.ident.name, args); - single_char_add_str::check(cx, expr, args); - into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, args); - single_char_pattern::check(cx, expr, method_call.ident.name, args); - unnecessary_to_owned::check(cx, expr, method_call.ident.name, args, self.msrv); + or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); + expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); + clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args); + clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args); + inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args); + single_char_add_str::check(cx, expr, receiver, args); + into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver); + single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args); + unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv); }, hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { @@ -3303,9 +3305,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // one of the associated types must be Self for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { - let assoc_ty = match projection_predicate.term { - ty::Term::Ty(ty) => ty, - ty::Term::Const(_c) => continue, + let assoc_ty = match projection_predicate.term.unpack() { + ty::TermKind::Ty(ty) => ty, + ty::TermKind::Const(_c) => continue, }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { @@ -3380,7 +3382,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { impl Methods { #[allow(clippy::too_many_lines)] fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some((name, [recv, args @ ..], span)) = method_call(expr) { + if let Some((name, recv, args, span)) = method_call(expr) { match (name, args) { ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => { zst_offset::check(cx, expr, recv); @@ -3400,13 +3402,13 @@ impl Methods { ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv), ("collect", []) => match method_call(recv) { - Some((name @ ("cloned" | "copied"), [recv2], _)) => { + Some((name @ ("cloned" | "copied"), recv2, [], _)) => { iter_cloned_collect::check(cx, name, expr, recv2); }, - Some(("map", [m_recv, m_arg], _)) => { + Some(("map", m_recv, [m_arg], _)) => { map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv); }, - Some(("take", [take_self_arg, take_arg], _)) => { + Some(("take", take_self_arg, [take_arg], _)) => { if meets_msrv(self.msrv, msrvs::STR_REPEAT) { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } @@ -3414,26 +3416,26 @@ impl Methods { _ => {}, }, ("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) { - Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false), - Some((name2 @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => { + Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false), + Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _)) => { iter_count::check(cx, expr, recv2, name2); }, - Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg), - Some(("filter", [recv2, arg], _)) => bytecount::check(cx, expr, recv2, arg), - Some(("bytes", [recv2], _)) => bytes_count_to_len::check(cx, expr, recv, recv2), + Some(("map", _, [arg], _)) => suspicious_map::check(cx, expr, recv, arg), + Some(("filter", recv2, [arg], _)) => bytecount::check(cx, expr, recv2, arg), + Some(("bytes", recv2, [], _)) => bytes_count_to_len::check(cx, expr, recv, recv2), _ => {}, }, ("drain", [arg]) => { iter_with_drain::check(cx, expr, recv, span, arg); }, ("ends_with", [arg]) => { - if let ExprKind::MethodCall(_, _, span) = expr.kind { + if let ExprKind::MethodCall(.., span) = expr.kind { case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); } }, ("expect", [_]) => match method_call(recv) { - Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv), - Some(("err", [recv], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span), + Some(("ok", recv, [], _)) => ok_expect::check(cx, expr, recv), + Some(("err", recv, [], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span), _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), }, ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), @@ -3453,13 +3455,13 @@ impl Methods { flat_map_option::check(cx, expr, arg, span); }, ("flatten", []) => match method_call(recv) { - Some(("map", [recv, map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span), - Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true), + Some(("map", recv, [map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span), + Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true), _ => {}, }, ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span), ("for_each", [_]) => { - if let Some(("inspect", [_, _], span2)) = method_call(recv) { + if let Some(("inspect", _, [_], span2)) = method_call(recv) { inspect_for_each::check(cx, expr, span2); } }, @@ -3479,12 +3481,12 @@ impl Methods { iter_on_single_or_empty_collections::check(cx, expr, name, recv); }, ("join", [join_arg]) => { - if let Some(("collect", _, span)) = method_call(recv) { + if let Some(("collect", _, _, span)) = method_call(recv) { unnecessary_join::check(cx, expr, recv, join_arg, span); } }, ("last", []) | ("skip", [_]) => { - if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) { + if let Some((name2, recv2, args2, _span2)) = method_call(recv) { if let ("cloned", []) = (name2, args2) { iter_overeager_cloned::check(cx, expr, recv, recv2, false, false); } @@ -3499,7 +3501,7 @@ impl Methods { } else { map_err_ignore::check(cx, expr, m_arg); } - if let Some((name, [recv2, args @ ..], span2)) = method_call(recv) { + if let Some((name, recv2, args, span2)) = method_call(recv) { match (name, args) { ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv), ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv), @@ -3519,7 +3521,7 @@ impl Methods { manual_ok_or::check(cx, expr, recv, def, map); }, ("next", []) => { - if let Some((name2, [recv2, args2 @ ..], _)) = method_call(recv) { + if let Some((name2, recv2, args2, _)) = method_call(recv) { match (name2, args2) { ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false), ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg), @@ -3532,10 +3534,10 @@ impl Methods { } }, ("nth", [n_arg]) => match method_call(recv) { - Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg), - Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false), - Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false), - Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true), + Some(("bytes", recv2, [], _)) => bytes_nth::check(cx, expr, recv2, n_arg), + Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false), + Some(("iter", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false), + Some(("iter_mut", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true), _ => iter_nth_zero::check(cx, expr, recv, n_arg), }, ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"), @@ -3592,7 +3594,7 @@ impl Methods { }, ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), ("take", [_arg]) => { - if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) { + if let Some((name2, recv2, args2, _span2)) = method_call(recv) { if let ("cloned", []) = (name2, args2) { iter_overeager_cloned::check(cx, expr, recv, recv2, false, false); } @@ -3615,13 +3617,13 @@ impl Methods { }, ("unwrap", []) => { match method_call(recv) { - Some(("get", [recv, get_arg], _)) => { + Some(("get", recv, [get_arg], _)) => { get_unwrap::check(cx, expr, recv, get_arg, false); }, - Some(("get_mut", [recv, get_arg], _)) => { + Some(("get_mut", recv, [get_arg], _)) => { get_unwrap::check(cx, expr, recv, get_arg, true); }, - Some(("or", [recv, or_arg], or_span)) => { + Some(("or", recv, [or_arg], or_span)) => { or_then_unwrap::check(cx, expr, recv, or_arg, or_span); }, _ => {}, @@ -3630,19 +3632,19 @@ impl Methods { }, ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests), ("unwrap_or", [u_arg]) => match method_call(recv) { - Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => { + Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _)) => { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, - Some(("map", [m_recv, m_arg], span)) => { + Some(("map", m_recv, [m_arg], span)) => { option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); }, - Some(("then_some", [t_recv, t_arg], _)) => { + Some(("then_some", t_recv, [t_arg], _)) => { obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); }, _ => {}, }, ("unwrap_or_else", [u_arg]) => match method_call(recv) { - Some(("map", [recv, map_arg], _)) + Some(("map", recv, [map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, _ => { unwrap_or_else_default::check(cx, expr, recv, u_arg); @@ -3650,7 +3652,7 @@ impl Methods { }, }, ("zip", [arg]) => { - if let ExprKind::MethodCall(name, [iter_recv], _) = recv.kind + if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind && name.ident.name == sym::iter { range_zip_with_len::check(cx, expr, iter_recv, arg); @@ -3663,7 +3665,7 @@ impl Methods { } fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) { - if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call(recv) { + if let Some((name @ ("find" | "position" | "rposition"), f_recv, [arg], span)) = method_call(recv) { search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span); } } diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index c3112823e3469..597af853dc681 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -36,12 +36,12 @@ enum OpenOption { } fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { - if let ExprKind::MethodCall(path, arguments, _) = argument.kind { - let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs(); + if let ExprKind::MethodCall(path, receiver, arguments, _) = argument.kind { + let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); // Only proceed if this is a call on some object of type std::fs::OpenOptions - if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { - let argument_option = match arguments[1].kind { + if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && !arguments.is_empty() { + let argument_option = match arguments[0].kind { ExprKind::Lit(ref span) => { if let Spanned { node: LitKind::Bool(lit), @@ -77,7 +77,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec _ => (), } - get_open_options(cx, &arguments[0], options); + get_open_options(cx, receiver, options); } } } diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 20cad0f181e95..c409268de769d 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -53,16 +53,15 @@ pub(super) fn check<'tcx>( }), hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(&closure_body.value); + let closure_expr = peel_blocks(closure_body.value); match &closure_expr.kind { - hir::ExprKind::MethodCall(_, args, _) => { + hir::ExprKind::MethodCall(_, receiver, [], _) => { if_chain! { - if args.len() == 1; - if path_to_local_id(&args[0], closure_body.params[0].pat.hir_id); + if path_to_local_id(receiver, closure_body.params[0].pat.hir_id); let adj = cx .typeck_results() - .expr_adjustments(&args[0]) + .expr_adjustments(receiver) .iter() .map(|x| &x.kind) .collect::>(); diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs index 5a39b82b027d1..6657cdccd010c 100644 --- a/clippy_lints/src/methods/option_map_or_none.rs +++ b/clippy_lints/src/methods/option_map_or_none.rs @@ -74,7 +74,7 @@ pub(super) fn check<'tcx>( if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind; let arg_snippet = snippet(cx, fn_decl_span, ".."); let body = cx.tcx.hir().body(body); - if let Some((func, [arg_char])) = reduce_unit_expression(&body.value); + if let Some((func, [arg_char])) = reduce_unit_expression(body.value); if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id)); if Some(id) == cx.tcx.lang_items().option_some_variant(); then { diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index c97f714680ef1..b43b9258c471d 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -20,6 +20,7 @@ pub(super) fn check<'tcx>( expr: &hir::Expr<'_>, method_span: Span, name: &str, + receiver: &'tcx hir::Expr<'_>, args: &'tcx [hir::Expr<'_>], ) { /// Checks for `unwrap_or(T::new())`, `unwrap_or(T::default())`, @@ -149,7 +150,7 @@ pub(super) fn check<'tcx>( } } - if let [self_arg, arg] = args { + if let [arg] = args { let inner_arg = if let hir::ExprKind::Block( hir::Block { stmts: [], @@ -168,11 +169,11 @@ pub(super) fn check<'tcx>( let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, arg, or_has_args, expr.span, method_span) { let fun_span = if or_has_args { None } else { Some(fun.span) }; - check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span); + check_general_case(cx, name, method_span, receiver, arg, expr.span, fun_span); } }, hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => { - check_general_case(cx, name, method_span, self_arg, arg, expr.span, None); + check_general_case(cx, name, method_span, receiver, arg, expr.span, None); }, _ => (), } diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs index 00a2a0d14d113..867a3b4023770 100644 --- a/clippy_lints/src/methods/range_zip_with_len.rs +++ b/clippy_lints/src/methods/range_zip_with_len.rs @@ -16,7 +16,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg); if is_integer_const(cx, start, 0); // `.len()` call - if let ExprKind::MethodCall(len_path, [len_recv], _) = end.kind; + if let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind; if len_path.ident.name == sym::len; // `.iter()` and `.len()` called on same `Path` if let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind; diff --git a/clippy_lints/src/methods/single_char_add_str.rs b/clippy_lints/src/methods/single_char_add_str.rs index 9a5fabcf7cd50..81450fd8c6c3c 100644 --- a/clippy_lints/src/methods/single_char_add_str.rs +++ b/clippy_lints/src/methods/single_char_add_str.rs @@ -3,12 +3,12 @@ use clippy_utils::{match_def_path, paths}; use rustc_hir as hir; use rustc_lint::LateContext; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { - single_char_push_string::check(cx, expr, args); + single_char_push_string::check(cx, expr, receiver, args); } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) { - single_char_insert_string::check(cx, expr, args); + single_char_insert_string::check(cx, expr, receiver, args); } } } diff --git a/clippy_lints/src/methods/single_char_insert_string.rs b/clippy_lints/src/methods/single_char_insert_string.rs index 6cdc954c03be1..18b6b5be175d1 100644 --- a/clippy_lints/src/methods/single_char_insert_string.rs +++ b/clippy_lints/src/methods/single_char_insert_string.rs @@ -8,12 +8,12 @@ use rustc_lint::LateContext; use super::SINGLE_CHAR_ADD_STR; /// lint for length-1 `str`s as argument for `insert_str` -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; - if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[2], &mut applicability) { + if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) { let base_string_snippet = - snippet_with_applicability(cx, args[0].span.source_callsite(), "_", &mut applicability); - let pos_arg = snippet_with_applicability(cx, args[1].span, "..", &mut applicability); + snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability); + let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability); let sugg = format!("{}.insert({}, {})", base_string_snippet, pos_arg, extension_string); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs index bf9006c690621..4221c52d5cd79 100644 --- a/clippy_lints/src/methods/single_char_pattern.rs +++ b/clippy_lints/src/methods/single_char_pattern.rs @@ -10,37 +10,43 @@ use rustc_span::symbol::Symbol; use super::SINGLE_CHAR_PATTERN; const PATTERN_METHODS: [(&str, usize); 24] = [ - ("contains", 1), - ("starts_with", 1), - ("ends_with", 1), - ("find", 1), - ("rfind", 1), - ("split", 1), - ("split_inclusive", 1), - ("rsplit", 1), - ("split_terminator", 1), - ("rsplit_terminator", 1), - ("splitn", 2), - ("rsplitn", 2), - ("split_once", 1), - ("rsplit_once", 1), - ("matches", 1), - ("rmatches", 1), - ("match_indices", 1), - ("rmatch_indices", 1), - ("strip_prefix", 1), - ("strip_suffix", 1), - ("trim_start_matches", 1), - ("trim_end_matches", 1), - ("replace", 1), - ("replacen", 1), + ("contains", 0), + ("starts_with", 0), + ("ends_with", 0), + ("find", 0), + ("rfind", 0), + ("split", 0), + ("split_inclusive", 0), + ("rsplit", 0), + ("split_terminator", 0), + ("rsplit_terminator", 0), + ("splitn", 1), + ("rsplitn", 1), + ("split_once", 0), + ("rsplit_once", 0), + ("matches", 0), + ("rmatches", 0), + ("match_indices", 0), + ("rmatch_indices", 0), + ("strip_prefix", 0), + ("strip_suffix", 0), + ("trim_start_matches", 0), + ("trim_end_matches", 0), + ("replace", 0), + ("replacen", 0), ]; /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { +pub(super) fn check( + cx: &LateContext<'_>, + _expr: &hir::Expr<'_>, + method_name: Symbol, + receiver: &hir::Expr<'_>, + args: &[hir::Expr<'_>], +) { for &(method, pos) in &PATTERN_METHODS { if_chain! { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind(); + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind(); if *ty.kind() == ty::Str; if method_name.as_str() == method && args.len() > pos; let arg = &args[pos]; diff --git a/clippy_lints/src/methods/single_char_push_string.rs b/clippy_lints/src/methods/single_char_push_string.rs index 0237d39cbdb4e..9ea6751956abb 100644 --- a/clippy_lints/src/methods/single_char_push_string.rs +++ b/clippy_lints/src/methods/single_char_push_string.rs @@ -8,11 +8,11 @@ use rustc_lint::LateContext; use super::SINGLE_CHAR_ADD_STR; /// lint for length-1 `str`s as argument for `push_str` -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; - if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) { + if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) { let base_string_snippet = - snippet_with_applicability(cx, args[0].span.source_callsite(), "..", &mut applicability); + snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability); let sugg = format!("{}.push({})", base_string_snippet, extension_string); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 4ac738272d085..9ca4d65550d3e 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -130,7 +130,7 @@ fn check_manual_split_once_indirect( let ctxt = expr.span.ctxt(); let mut parents = cx.tcx.hir().parent_iter(expr.hir_id); if let (_, Node::Local(local)) = parents.next()? - && let PatKind::Binding(BindingAnnotation::Mutable, iter_binding_id, iter_ident, None) = local.pat.kind + && let PatKind::Binding(BindingAnnotation::MUT, iter_binding_id, iter_ident, None) = local.pat.kind && let (iter_stmt_id, Node::Stmt(_)) = parents.next()? && let (_, Node::Block(enclosing_block)) = parents.next()? @@ -212,11 +212,10 @@ fn indirect_usage<'tcx>( ctxt: SyntaxContext, ) -> Option> { if let StmtKind::Local(Local { - pat: - Pat { - kind: PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None), - .. - }, + pat: Pat { + kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None), + .. + }, init: Some(init_expr), hir_id: local_hir_id, .. @@ -292,7 +291,7 @@ fn parse_iter_usage<'tcx>( ) -> Option { let (kind, span) = match iter.next() { Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => { - let (name, args) = if let ExprKind::MethodCall(name, [_, args @ ..], _) = e.kind { + let (name, args) = if let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind { (name, args) } else { return None; @@ -327,7 +326,7 @@ fn parse_iter_usage<'tcx>( } else { if_chain! { if let Some((_, Node::Expr(next_expr))) = iter.next(); - if let ExprKind::MethodCall(next_name, [_], _) = next_expr.kind; + if let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind; if next_name.ident.name == sym::next; if next_expr.span.ctxt() == ctxt; if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id); @@ -367,7 +366,7 @@ fn parse_iter_usage<'tcx>( } }, _ if e.span.ctxt() != ctxt => (None, span), - ExprKind::MethodCall(name, [_], _) + ExprKind::MethodCall(name, _, [], _) if name.ident.name == sym::unwrap && cx .typeck_results() diff --git a/clippy_lints/src/methods/string_extend_chars.rs b/clippy_lints/src/methods/string_extend_chars.rs index d06658f2a5e6e..143dcee350521 100644 --- a/clippy_lints/src/methods/string_extend_chars.rs +++ b/clippy_lints/src/methods/string_extend_chars.rs @@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr return; } if let Some(arglists) = method_chain_args(arg, &["chars"]) { - let target = &arglists[0][0]; + let target = &arglists[0].0; let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); let ref_str = if *self_ty.kind() == ty::Str { "" diff --git a/clippy_lints/src/methods/suspicious_map.rs b/clippy_lints/src/methods/suspicious_map.rs index 9c3375bf35e7d..851cdf544550f 100644 --- a/clippy_lints/src/methods/suspicious_map.rs +++ b/clippy_lints/src/methods/suspicious_map.rs @@ -15,9 +15,9 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hi if let Some(def_id) = cx.tcx.hir().opt_local_def_id(closure.hir_id); if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id); let closure_body = cx.tcx.hir().body(body_id); - if !cx.typeck_results().expr_ty(&closure_body.value).is_unit(); + if !cx.typeck_results().expr_ty(closure_body.value).is_unit(); then { - if let Some(map_mutated_vars) = mutated_variables(&closure_body.value, cx) { + if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) { // A variable is used mutably inside of the closure. Suppress the lint. if !map_mutated_vars.is_empty() { return; diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index bafa6fc584d48..4e8c201f470ba 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -21,14 +21,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr< if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { let body = cx.tcx.hir().body(body); let arg_id = body.params[0].pat.hir_id; - let mutates_arg = - mutated_variables(&body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id)); - let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, &body.value); + let mutates_arg = mutated_variables(body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id)); + let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value); - let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, &body.value); + let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value); let mut return_visitor = ReturnVisitor::new(cx, arg_id); - return_visitor.visit_expr(&body.value); + return_visitor.visit_expr(body.value); found_mapping |= return_visitor.found_mapping; found_filtering |= return_visitor.found_filtering; @@ -36,7 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr< let sugg = if !found_filtering { if name == "filter_map" { "map" } else { "map(..).next()" } } else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) { - match cx.typeck_results().expr_ty(&body.value).kind() { + match cx.typeck_results().expr_ty(body.value).kind() { ty::Adt(adt, subst) if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && in_ty == subst.type_at(0) => { diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index c3531d4d0511e..c17ef6809f912 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -31,7 +31,7 @@ pub(super) fn check( // Extract the body of the closure passed to fold if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(&closure_body.value); + let closure_expr = peel_blocks(closure_body.value); // Check if the closure body is of the form `acc some_expr(x)` if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 19037093e20a1..95138c0e25b03 100644 --- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -43,7 +43,7 @@ pub fn check_for_loop_iter( if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); then { let snippet = if_chain! { - if let ExprKind::MethodCall(maybe_iter_method_name, [collection], _) = receiver.kind; + if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind; if maybe_iter_method_name.ident.name == sym::iter; if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 1876c7fb9d051..a187a8d6016f8 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -54,7 +54,7 @@ pub(super) fn check<'tcx>( // This is a duplicate of what's happening in clippy_lints::methods::method_call, // which isn't ideal, We want to get the method call span, // but prefer to avoid changing the signature of the function itself. - if let hir::ExprKind::MethodCall(_, _, span) = expr.kind { + if let hir::ExprKind::MethodCall(.., span) = expr.kind { span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { diag.span_suggestion( span, diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 1966990bd774f..ed5a75b0f3ce5 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -50,9 +50,13 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident // The two exprs are method calls. // Check to see that the function is the same and the arguments are mirrored // This is enough because the receiver of the method is listed in the arguments - (ExprKind::MethodCall(left_segment, left_args, _), ExprKind::MethodCall(right_segment, right_args, _)) => { + ( + ExprKind::MethodCall(left_segment, left_receiver, left_args, _), + ExprKind::MethodCall(right_segment, right_receiver, right_args, _), + ) => { left_segment.ident == right_segment.ident && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) + && mirrored_exprs(left_receiver, a_ident, right_receiver, b_ident) }, // Two tuples with mirrored contents (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => { @@ -125,9 +129,9 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..}, Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. } ] = &closure_body.params; - if let ExprKind::MethodCall(method_path, [left_expr, right_expr], _) = closure_body.value.kind; + if let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind; if method_path.ident.name == sym::cmp; - if is_trait_method(cx, &closure_body.value, sym::Ord); + if is_trait_method(cx, closure_body.value, sym::Ord); then { let (closure_body, closure_arg, reverse) = if mirrored_exprs( left_expr, diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index d59b26c314423..763bfafecef14 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -28,12 +28,13 @@ pub fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: Symbol, - args: &'tcx [Expr<'tcx>], + receiver: &'tcx Expr<'_>, + args: &'tcx [Expr<'_>], msrv: Option, ) { if_chain! { if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let [receiver] = args; + if args.is_empty(); then { if is_cloned_or_copied(cx, method_name, method_def_id) { unnecessary_iter_cloned::check(cx, expr, method_name, receiver); @@ -249,9 +250,9 @@ fn check_other_call_arg<'tcx>( ) -> bool { if_chain! { if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr); - if let Some((callee_def_id, _, call_args)) = get_callee_substs_and_args(cx, maybe_call); + if let Some((callee_def_id, _, recv, call_args)) = get_callee_substs_and_args(cx, maybe_call); let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder(); - if let Some(i) = call_args.iter().position(|arg| arg.hir_id == maybe_arg.hir_id); + if let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id); if let Some(input) = fn_sig.inputs().get(i); let (input, n_refs) = peel_mid_ty_refs(*input); if let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input); @@ -307,22 +308,22 @@ fn skip_addr_of_ancestors<'tcx>( fn get_callee_substs_and_args<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, -) -> Option<(DefId, SubstsRef<'tcx>, &'tcx [Expr<'tcx>])> { +) -> Option<(DefId, SubstsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> { if_chain! { if let ExprKind::Call(callee, args) = expr.kind; let callee_ty = cx.typeck_results().expr_ty(callee); if let ty::FnDef(callee_def_id, _) = callee_ty.kind(); then { let substs = cx.typeck_results().node_substs(callee.hir_id); - return Some((*callee_def_id, substs, args)); + return Some((*callee_def_id, substs, None, args)); } } if_chain! { - if let ExprKind::MethodCall(_, args, _) = expr.kind; + if let ExprKind::MethodCall(_, recv, args, _) = expr.kind; if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); then { let substs = cx.typeck_results().node_substs(expr.hir_id); - return Some((method_def_id, substs, args)); + return Some((method_def_id, substs, Some(recv), args)); } } None @@ -377,9 +378,10 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< } } Node::Expr(parent_expr) => { - if let Some((callee_def_id, call_substs, call_args)) = get_callee_substs_and_args(cx, parent_expr) { + if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr) + { let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder(); - if let Some(arg_index) = call_args.iter().position(|arg| arg.hir_id == expr.hir_id) + if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id) && let Some(param_ty) = fn_sig.inputs().get(arg_index) && let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind() { diff --git a/clippy_lints/src/methods/unwrap_or_else_default.rs b/clippy_lints/src/methods/unwrap_or_else_default.rs index d3630b7d08eaa..045f739e64ded 100644 --- a/clippy_lints/src/methods/unwrap_or_else_default.rs +++ b/clippy_lints/src/methods/unwrap_or_else_default.rs @@ -52,7 +52,7 @@ fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) if body.params.is_empty() && let hir::Expr{ kind, .. } = &body.value - && let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, [self_arg], _) = kind + && let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, self_arg, _, _) = kind && ident == &symbol::Ident::from_str("to_string") && let hir::Expr{ kind, .. } = self_arg && let hir::ExprKind::Lit(lit) = kind diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 3015531e84393..ae6b165fdc366 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -28,7 +28,7 @@ pub(super) fn derefs_to_slice<'tcx>( } } - if let hir::ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind { + if let hir::ExprKind::MethodCall(path, self_arg, ..) = &expr.kind { if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) { Some(self_arg) } else { @@ -139,9 +139,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> { self.addr_of_exprs.push(parent); return; }, - ExprKind::MethodCall(_, args, _) => { + ExprKind::MethodCall(.., args, _) => { if_chain! { - if args.iter().skip(1).all(|arg| !self.is_binding(arg)); + if args.iter().all(|arg| !self.is_binding(arg)); if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id); let method_ty = self.cx.tcx.type_of(method_def_id); let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder(); diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index a081cde85725b..4d8579135fc06 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,7 +1,6 @@ use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{match_trait_method, paths}; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -75,45 +74,49 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons .qpath_res(qpath, path.hir_id) .opt_def_id() .and_then(|def_id| match cx.tcx.get_diagnostic_name(def_id) { - Some(sym::cmp_min) => fetch_const(cx, args, MinMax::Min), - Some(sym::cmp_max) => fetch_const(cx, args, MinMax::Max), + Some(sym::cmp_min) => fetch_const(cx, None, args, MinMax::Min), + Some(sym::cmp_max) => fetch_const(cx, None, args, MinMax::Max), _ => None, }) } else { None } }, - ExprKind::MethodCall(path, args, _) => { - if_chain! { - if let [obj, _] = args; - if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD); - then { - if path.ident.name == sym!(max) { - fetch_const(cx, args, MinMax::Max) - } else if path.ident.name == sym!(min) { - fetch_const(cx, args, MinMax::Min) - } else { - None - } + ExprKind::MethodCall(path, receiver, args @ [_], _) => { + if cx.typeck_results().expr_ty(receiver).is_floating_point() || match_trait_method(cx, expr, &paths::ORD) { + if path.ident.name == sym!(max) { + fetch_const(cx, Some(receiver), args, MinMax::Max) + } else if path.ident.name == sym!(min) { + fetch_const(cx, Some(receiver), args, MinMax::Min) } else { None } + } else { + None } }, _ => None, } } -fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Option<(MinMax, Constant, &'a Expr<'a>)> { - if args.len() != 2 { +fn fetch_const<'a>( + cx: &LateContext<'_>, + receiver: Option<&'a Expr<'a>>, + args: &'a [Expr<'a>], + m: MinMax, +) -> Option<(MinMax, Constant, &'a Expr<'a>)> { + let mut args = receiver.into_iter().chain(args); + let first_arg = args.next()?; + let second_arg = args.next()?; + if args.next().is_some() { return None; } - constant_simple(cx, cx.typeck_results(), &args[0]).map_or_else( - || constant_simple(cx, cx.typeck_results(), &args[1]).map(|c| (m, c, &args[0])), + constant_simple(cx, cx.typeck_results(), first_arg).map_or_else( + || constant_simple(cx, cx.typeck_results(), second_arg).map(|c| (m, c, first_arg)), |c| { - if constant_simple(cx, cx.typeck_results(), &args[1]).is_none() { + if constant_simple(cx, cx.typeck_results(), second_arg).is_none() { // otherwise ignore - Some((m, c, &args[1])) + Some((m, c, second_arg)) } else { None } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 8224e80c9ccb3..ea245edd77040 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -5,8 +5,8 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, - StmtKind, TyKind, + self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, + Stmt, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { return; } for arg in iter_input_pats(decl, body) { - if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind { + if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind { span_lint( cx, TOPLEVEL_REF_ARG, @@ -162,9 +162,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { if_chain! { if !in_external_macro(cx.tcx.sess, stmt.span); if let StmtKind::Local(local) = stmt.kind; - if let PatKind::Binding(an, .., name, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind; if let Some(init) = local.init; - if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut; then { // use the macro callsite when the init span (but not the whole local span) // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];` @@ -173,7 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { } else { Sugg::hir(cx, init, "..") }; - let (mutopt, initref) = if an == BindingAnnotation::RefMut { + let (mutopt, initref) = if mutabl == Mutability::Mut { ("mut ", sugg_init.mut_addr()) } else { ("", sugg_init.addr()) diff --git a/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs index 525dbf7757c14..d7bb0616acb0b 100644 --- a/clippy_lints/src/misc_early/redundant_pattern.rs +++ b/clippy_lints/src/misc_early/redundant_pattern.rs @@ -1,18 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use rustc_ast::ast::{BindingMode, Mutability, Pat, PatKind}; +use rustc_ast::ast::{Pat, PatKind}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; use super::REDUNDANT_PATTERN; pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { - if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind { - let left_binding = match left { - BindingMode::ByRef(Mutability::Mut) => "ref mut ", - BindingMode::ByRef(Mutability::Not) => "ref ", - BindingMode::ByValue(..) => "", - }; - + if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind { if let PatKind::Wild = right.kind { span_lint_and_sugg( cx, @@ -23,7 +17,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { ident.name, ident.name, ), "try", - format!("{}{}", left_binding, ident.name), + format!("{}{}", ann.prefix_str(), ident.name), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index f434a655f8aff..82dc03ef5c5bc 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -43,18 +43,24 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { if let ExprKind::Path(ref path) = fn_expr.kind { check_arguments( cx, - arguments, + arguments.iter().collect(), cx.typeck_results().expr_ty(fn_expr), &rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)), "function", ); } }, - ExprKind::MethodCall(path, arguments, _) => { + ExprKind::MethodCall(path, receiver, arguments, _) => { let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap(); let substs = cx.typeck_results().node_substs(e.hir_id); let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs); - check_arguments(cx, arguments, method_type, path.ident.as_str(), "method"); + check_arguments( + cx, + std::iter::once(receiver).chain(arguments.iter()).collect(), + method_type, + path.ident.as_str(), + "method", + ); }, _ => (), } @@ -63,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { fn check_arguments<'tcx>( cx: &LateContext<'tcx>, - arguments: &[Expr<'_>], + arguments: Vec<&Expr<'_>>, type_definition: Ty<'tcx>, name: &str, fn_kind: &str, diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs index 9838d3cad9f02..f2ffac85bf402 100644 --- a/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use if_chain::if_chain; -use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind}; +use rustc_ast::ast::{BindingAnnotation, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -120,14 +120,14 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { match &p.ty.kind { TyKind::Path(None, path) => { - if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind { + if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), _, _) = p.pat.kind { check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl); } }, TyKind::Rptr(lifetime, mut_ty) => { if_chain! { if let TyKind::Path(None, path) = &mut_ty.ty.kind; - if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind; + if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind; then { check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl); } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 05c012b92e878..b8855e5adbff4 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef { if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind; // Check sub_pat got a `ref` keyword (excluding `ref mut`). - if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.kind; + if let PatKind::Binding(BindingAnnotation::REF, .., spanned_name, _) = sub_pat.kind; let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id); if let Some(parent_node) = cx.tcx.hir().find(parent_id); then { diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs index 10e188ecb79a6..3233d87c07319 100644 --- a/clippy_lints/src/needless_for_each.rs +++ b/clippy_lints/src/needless_for_each.rs @@ -56,12 +56,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach { if_chain! { // Check the method name is `for_each`. - if let ExprKind::MethodCall(method_name, [for_each_recv, for_each_arg], _) = expr.kind; + if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind; if method_name.ident.name == Symbol::intern("for_each"); // Check `for_each` is an associated function of `Iterator`. if is_trait_method(cx, expr, sym::Iterator); // Checks the receiver of `for_each` is also a method call. - if let ExprKind::MethodCall(_, [iter_recv], _) = for_each_recv.kind; + if let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind; // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or // `v.foo().iter().for_each()` must be skipped. if matches!( @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach { if let ExprKind::Block(..) = body.value.kind; then { let mut ret_collector = RetCollector::default(); - ret_collector.visit_expr(&body.value); + ret_collector.visit_expr(body.value); // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`. if ret_collector.ret_in_loop { diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs index ff2999b1f4a51..de99f1d7078e9 100644 --- a/clippy_lints/src/needless_late_init.rs +++ b/clippy_lints/src/needless_late_init.rs @@ -373,7 +373,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit { if let Local { init: None, pat: &Pat { - kind: PatKind::Binding(BindingAnnotation::Unannotated, binding_id, _, None), + kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None), .. }, source: LocalSource::Normal, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 0cbef1c95fe95..6d17c7a7346f3 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -8,7 +8,9 @@ use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind}; +use rustc_hir::{ + BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind, +}; use rustc_hir::{HirIdMap, HirIdSet}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; @@ -188,13 +190,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !implements_borrow_trait; if !all_borrowable_trait; - if let PatKind::Binding(mode, canonical_id, ..) = arg.pat.kind; + if let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind; if !moved_vars.contains(&canonical_id); then { - if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { - continue; - } - // Dereference suggestion let sugg = |diag: &mut Diagnostic| { if let ty::Adt(def, ..) = ty.kind() { diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs index ed022b9d5291c..25fb4f0f4cff1 100644 --- a/clippy_lints/src/non_octal_unix_permissions.rs +++ b/clippy_lints/src/non_octal_unix_permissions.rs @@ -43,7 +43,7 @@ declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]); impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { match &expr.kind { - ExprKind::MethodCall(path, [func, param], _) => { + ExprKind::MethodCall(path, func, [param], _) => { let obj_ty = cx.typeck_results().expr_ty(func).peel_refs(); if_chain! { diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs index c55478b3441f1..6217110a1f3ae 100644 --- a/clippy_lints/src/only_used_in_recursion.rs +++ b/clippy_lints/src/only_used_in_recursion.rs @@ -12,6 +12,7 @@ use rustc_middle::ty::{self, ConstKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; +use std::iter; declare_clippy_lint! { /// ### What it does @@ -296,13 +297,13 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { } return; }, - ExprKind::MethodCall(_, args, _) + ExprKind::MethodCall(_, receiver, args, _) if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| { id == param.fn_id && has_matching_substs(param.fn_kind, typeck.node_substs(parent.hir_id)) }) => { - if let Some(idx) = args.iter().position(|arg| arg.hir_id == child_id) { + if let Some(idx) = iter::once(receiver).chain(args).position(|arg| arg.hir_id == child_id) { param.uses.push(Usage::new(span, idx)); } return; diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index e1f9b5906f667..638a514ff9b36 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -38,7 +38,7 @@ fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'t fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { let typeck = cx.typeck_results(); let (arg, arg_span) = match expr.kind { - ExprKind::MethodCall(.., [arg], _) + ExprKind::MethodCall(_, arg, [], _) if typeck .type_dependent_def_id(expr.hir_id) .and_then(|id| cx.tcx.trait_of_item(id)) diff --git a/clippy_lints/src/operators/duration_subsec.rs b/clippy_lints/src/operators/duration_subsec.rs index 0d067d1e1968c..827a2b2670935 100644 --- a/clippy_lints/src/operators/duration_subsec.rs +++ b/clippy_lints/src/operators/duration_subsec.rs @@ -17,7 +17,7 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if op == BinOpKind::Div - && let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind + && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration) && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right) { diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs index 0ef793443ff45..97ddcdb24799d 100644 --- a/clippy_lints/src/operators/float_cmp.rs +++ b/clippy_lints/src/operators/float_cmp.rs @@ -113,7 +113,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } if_chain! { - if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = expr.kind; + if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind; if sym!(signum) == method_name.ident.name; // Check that the receiver of the signum() is a float (expressions[0] is the receiver of // the method call) diff --git a/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs index 1805672e37254..1085e60894415 100644 --- a/clippy_lints/src/operators/op_ref.rs +++ b/clippy_lints/src/operators/op_ref.rs @@ -185,7 +185,7 @@ fn in_impl<'tcx>( if let ItemKind::Impl(item) = &item.kind; if let Some(of_trait) = &item.of_trait; if let Some(seg) = of_trait.path.segments.last(); - if let Some(Res::Def(_, trait_id)) = seg.res; + if let Res::Def(_, trait_id) = seg.res; if trait_id == bin_op; if let Some(generic_args) = seg.args; if let Some(GenericArg::Type(other_ty)) = generic_args.args.last(); diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 9602d0d1d2ea1..0315678bf97a9 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -130,7 +130,7 @@ fn try_get_option_occurence<'tcx>( .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2))) .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref()); then { - let capture_mut = if bind_annotation == BindingAnnotation::Mutable { "mut " } else { "" }; + let capture_mut = if bind_annotation == BindingAnnotation::MUT { "mut " } else { "" }; let some_body = peel_blocks(if_then); let none_body = peel_blocks(if_else); let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" }; @@ -138,7 +138,7 @@ fn try_get_option_occurence<'tcx>( let (as_ref, as_mut) = match &expr.kind { ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), - _ => (bind_annotation == BindingAnnotation::Ref, bind_annotation == BindingAnnotation::RefMut), + _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT), }; // Check if captures the closure will need conflict with borrows made in the scrutinee. diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs index 21acf003d92b2..4aa0d9227abad 100644 --- a/clippy_lints/src/panic_in_result_fn.rs +++ b/clippy_lints/src/panic_in_result_fn.rs @@ -69,7 +69,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir } true }) - .visit_expr(&body.value); + .visit_expr(body.value); if !panics.is_empty() { span_lint_and_then( cx, diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 5fa4fd74853f1..0960b050c240e 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -221,7 +221,7 @@ impl<'tcx> PassByRefOrValue { // if function has a body and parameter is annotated with mut, ignore if let Some(param) = fn_body.and_then(|body| body.params.get(index)) { match param.pat.kind { - PatKind::Binding(BindingAnnotation::Unannotated, _, _, _) => {}, + PatKind::Binding(BindingAnnotation::NONE, _, _, _) => {}, _ => continue, } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 3c5ea2d94144f..41d1baba64f85 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -507,7 +507,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio if let Some(args) = args && !args.is_empty() && body.map_or(true, |body| { - sig.header.unsafety == Unsafety::Unsafe || contains_unsafe_block(cx, &body.value) + sig.header.unsafety == Unsafety::Unsafe || contains_unsafe_block(cx, body.value) }) { span_lint_and_then( @@ -571,7 +571,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: Some((Node::Stmt(_), _)) => (), Some((Node::Local(l), _)) => { // Only trace simple bindings. e.g `let x = y;` - if let PatKind::Binding(BindingAnnotation::Unannotated, id, _, None) = l.pat.kind { + if let PatKind::Binding(BindingAnnotation::NONE, id, _, None) = l.pat.kind { self.bindings.insert(id, args_idx); } else { set_skip_flag(); @@ -591,8 +591,11 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: set_skip_flag(); } }, - ExprKind::MethodCall(name, expr_args @ [self_arg, ..], _) => { - let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0); + ExprKind::MethodCall(name, self_arg, expr_args, _) => { + let i = std::iter::once(self_arg) + .chain(expr_args.iter()) + .position(|arg| arg.hir_id == child_id) + .unwrap_or(0); if i == 0 { // Check if the method can be renamed. let name = name.ident.as_str(); @@ -644,7 +647,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: .filter_map(|(i, arg)| { let param = &body.params[arg.idx]; match param.pat.kind { - PatKind::Binding(BindingAnnotation::Unannotated, id, _, None) + PatKind::Binding(BindingAnnotation::NONE, id, _, None) if !is_lint_allowed(cx, PTR_ARG, param.hir_id) => { Some((id, i)) @@ -661,7 +664,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: results, skip_count, }; - v.visit_expr(&body.value); + v.visit_expr(body.value); v.results } diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index b907f38afbb92..4dc65da3ea1fd 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -93,7 +93,7 @@ fn expr_as_ptr_offset_call<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { - if let ExprKind::MethodCall(path_segment, [arg_0, arg_1, ..], _) = &expr.kind { + if let ExprKind::MethodCall(path_segment, arg_0, [arg_1, ..], _) = &expr.kind { if is_expr_ty_raw_ptr(cx, arg_0) { if path_segment.ident.name == sym::offset { return Some((arg_0, arg_1, Method::Offset)); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b432ccb1ee32d..f4f1fd336df7c 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -9,7 +9,7 @@ use clippy_utils::{ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; -use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, PathSegment, QPath}; +use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -86,7 +86,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex if_chain! { if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); if !is_else_clause(cx.tcx, expr); - if let ExprKind::MethodCall(segment, [caller, ..], _) = &cond.kind; + if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; let caller_ty = cx.typeck_results().expr_ty(caller); let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); @@ -123,7 +123,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); if !is_else_clause(cx.tcx, expr); if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind; - if let PatKind::Binding(annot, bind_id, ident, None) = field.kind; + if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; let caller_ty = cx.typeck_results().expr_ty(let_expr); let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else); if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) @@ -132,12 +132,11 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: then { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut); let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); let sugg = format!( "{}{}?{}", receiver_str, - if by_ref { ".as_ref()" } else { "" }, + if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, if requires_semi { ";" } else { "" } ); span_lint_and_sugg( diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index 9538a8104739e..94dec191103c5 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { // finds use of `_.read(&mut v)` let mut read_found = false; let mut visitor = expr_visitor_no_bodies(|expr| { - if let ExprKind::MethodCall(path, [_self, arg], _) = expr.kind + if let ExprKind::MethodCall(path, _self, [arg], _) = expr.kind && let PathSegment { ident: read_or_read_exact, .. } = *path && matches!(read_or_read_exact.as_str(), "read" | "read_exact") && let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index eddca60457574..9fd86331ec755 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { vis.into_map(cx, maybe_storage_live_result) }; - for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { + for (bb, bbdata) in mir.basic_blocks.iter_enumerated() { let terminator = bbdata.terminator(); if terminator.source_info.span.from_expansion() { @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { unwrap_or_continue!(find_stmt_assigns_to(cx, mir, pred_arg, true, ps[0])); let loc = mir::Location { block: bb, - statement_index: mir.basic_blocks()[bb].statements.len(), + statement_index: mir.basic_blocks[bb].statements.len(), }; // This can be turned into `res = move local` if `arg` and `cloned` are not borrowed @@ -310,7 +310,7 @@ fn find_stmt_assigns_to<'tcx>( by_ref: bool, bb: mir::BasicBlock, ) -> Option<(mir::Local, CannotMoveOut)> { - let rvalue = mir.basic_blocks()[bb].statements.iter().rev().find_map(|stmt| { + let rvalue = mir.basic_blocks[bb].statements.iter().rev().find_map(|stmt| { if let mir::StatementKind::Assign(box (mir::Place { local, .. }, v)) = &stmt.kind { return if *local == to_local { Some(v) } else { None }; } diff --git a/clippy_lints/src/ref_option_ref.rs b/clippy_lints/src/ref_option_ref.rs index 909d6971a5497..42514f861be1c 100644 --- a/clippy_lints/src/ref_option_ref.rs +++ b/clippy_lints/src/ref_option_ref.rs @@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { if mut_ty.mutbl == Mutability::Not; if let TyKind::Path(ref qpath) = &mut_ty.ty.kind; let last = last_path_segment(qpath); - if let Some(res) = last.res; - if let Some(def_id) = res.opt_def_id(); + if let Some(def_id) = last.res.opt_def_id(); if cx.tcx.is_diagnostic_item(sym::Option, def_id); if let Some(params) = last_path_segment(qpath).args ; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 1926661c59603..91553240e3c91 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { } else { RetReplacement::Empty }; - check_final_expr(cx, &body.value, Some(body.value.span), replacement); + check_final_expr(cx, body.value, Some(body.value.span), replacement); }, FnKind::ItemFn(..) | FnKind::Method(..) => { if let ExprKind::Block(block, _) = body.value.kind { diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index bfb9f0d01e1dc..ac4e29e9dfdfa 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -108,7 +108,7 @@ fn get_pointee_ty_and_count_expr<'tcx>( }; if_chain! { // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods - if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind; + if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind; let method_ident = method_path.ident.as_str(); if METHODS.iter().any(|m| *m == method_ident); diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index b59a25e3a4004..c07aa00a12789 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` if_chain! { if let StmtKind::Local(local) = stmt.kind; - if let PatKind::Binding(BindingAnnotation::Mutable, local_id, _, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind; if let Some(init) = local.init; if let Some(len_arg) = Self::is_vec_with_capacity(cx, init); @@ -201,7 +201,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) { if_chain! { if self.initialization_found; - if let ExprKind::MethodCall(path, [self_arg, extend_arg], _) = expr.kind; + if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind; if path_to_local_id(self_arg, self.vec_alloc.local_id); if path.ident.name == sym!(extend); if self.is_repeat_take(extend_arg); @@ -215,7 +215,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Checks if the given expression is resizing a vector with 0 fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) { if self.initialization_found - && let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind + && let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind && path_to_local_id(self_arg, self.vec_alloc.local_id) && path.ident.name == sym!(resize) // Check that is filled with 0 @@ -224,7 +224,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { // Check that len expression is equals to `with_capacity` expression if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) { self.slow_expression = Some(InitializationType::Resize(expr)); - } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" { + } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" { self.slow_expression = Some(InitializationType::Resize(expr)); } } @@ -233,7 +233,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&self, expr: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::MethodCall(take_path, [recv, len_arg, ..], _) = expr.kind; + if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind; if take_path.ident.name == sym!(take); // Check that take is applied to `repeat(0)` if self.is_repeat_zero(recv); @@ -241,7 +241,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { // Check that len expression is equals to `with_capacity` expression if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) { return true; - } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" { + } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" { return true; } } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 22eb06b364632..662d399ca538a 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -262,7 +262,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { let (method_names, expressions, _) = method_calls(left, 1); if method_names.len() == 1; if expressions.len() == 1; - if expressions[0].len() == 1; + if expressions[0].1.is_empty(); if method_names[0] == sym!(as_bytes); // Check for slicer @@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { then { let mut applicability = Applicability::MachineApplicable; - let string_expression = &expressions[0][0]; + let string_expression = &expressions[0].0; let snippet_app = snippet_with_applicability( cx, @@ -291,12 +291,12 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } if_chain! { - if let ExprKind::MethodCall(path, args, _) = &e.kind; + if let ExprKind::MethodCall(path, receiver, ..) = &e.kind; if path.ident.name == sym!(as_bytes); - if let ExprKind::Lit(lit) = &args[0].kind; + if let ExprKind::Lit(lit) = &receiver.kind; if let LitKind::Str(lit_content, _) = &lit.node; then { - let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#); + let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#); let mut applicability = Applicability::MachineApplicable; if callsite.starts_with("include_str!") { span_lint_and_sugg( @@ -305,7 +305,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { e.span, "calling `as_bytes()` on `include_str!(..)`", "consider using `include_bytes!(..)` instead", - snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen( + snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen( "include_str", "include_bytes", 1, @@ -314,7 +314,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { ); } else if lit_content.as_str().is_ascii() && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT - && !args[0].span.from_expansion() + && !receiver.span.from_expansion() { span_lint_and_sugg( cx, @@ -324,7 +324,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { "consider using a byte string literal instead", format!( "b{}", - snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability) + snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability) ), applicability, ); @@ -333,9 +333,9 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } if_chain! { - if let ExprKind::MethodCall(path, [recv], _) = &e.kind; + if let ExprKind::MethodCall(path, recv, [], _) = &e.kind; if path.ident.name == sym!(into_bytes); - if let ExprKind::MethodCall(path, [recv], _) = &recv.kind; + if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind; if matches!(path.ident.name.as_str(), "to_owned" | "to_string"); if let ExprKind::Lit(lit) = &recv.kind; if let LitKind::Str(lit_content, _) = &lit.node; @@ -393,7 +393,7 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StrToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind; + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; if path.ident.name == sym::to_string; let ty = cx.typeck_results().expr_ty(self_arg); if let ty::Ref(_, ty, ..) = ty.kind(); @@ -443,7 +443,7 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind; + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; if path.ident.name == sym::to_string; let ty = cx.typeck_results().expr_ty(self_arg); if is_type_diagnostic_item(cx, ty, sym::String); @@ -487,11 +487,11 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { let tyckres = cx.typeck_results(); if_chain! { - if let ExprKind::MethodCall(path, [split_recv], split_ws_span) = expr.kind; + if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind; if path.ident.name == sym!(split_whitespace); if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id); if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id); - if let ExprKind::MethodCall(path, [_trim_recv], trim_span) = split_recv.kind; + if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind; if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str(); if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id); if is_one_of_trim_diagnostic_items(cx, trim_def_id); diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index 7bc9cf742e654..78403d9fdb7e6 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { if let ExprKind::Path(path) = &func.kind; if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_libc_symbol(cx, did, "strlen"); - if let ExprKind::MethodCall(path, [self_arg], _) = recv.kind; + if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind; if !recv.span.from_expansion(); if path.ident.name == sym::as_ptr; then { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 4294464dbf61a..6add20c1fb712 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { ] .iter() .find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t))); - if count_binops(&body.value) == 1; + if count_binops(body.value) == 1; then { span_lint( cx, diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs index aa6c01b3a7cd9..651201f34ed28 100644 --- a/clippy_lints/src/to_digit_is_some.rs +++ b/clippy_lints/src/to_digit_is_some.rs @@ -39,19 +39,17 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]); impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { - if let hir::ExprKind::MethodCall(is_some_path, is_some_args, _) = &expr.kind; + if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind; if is_some_path.ident.name.as_str() == "is_some"; - if let [to_digit_expr] = &**is_some_args; then { let match_result = match &to_digit_expr.kind { - hir::ExprKind::MethodCall(to_digits_path, to_digit_args, _) => { + hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => { if_chain! { - if let [char_arg, radix_arg] = &**to_digit_args; if to_digits_path.ident.name.as_str() == "to_digit"; let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg); if *char_arg_ty.kind() == ty::Char; then { - Some((true, char_arg, radix_arg)) + Some((true, *char_arg, radix_arg)) } else { None } @@ -59,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { } hir::ExprKind::Call(to_digits_call, to_digit_args) => { if_chain! { - if let [char_arg, radix_arg] = &**to_digit_args; + if let [char_arg, radix_arg] = *to_digit_args; if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind; if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id); if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id(); diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 2ffa022b04f7a..a25be93b8d616 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { if !bound_predicate.span.from_expansion(); if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind; if let Some(PathSegment { - res: Some(Res::SelfTy{ trait_: Some(def_id), alias_to: _ }), .. + res: Res::SelfTy{ trait_: Some(def_id), alias_to: _ }, .. }) = segments.first(); if let Some( Node::Item( diff --git a/clippy_lints/src/uninit_vec.rs b/clippy_lints/src/uninit_vec.rs index 9a41603f2f4ce..3f99bd3f31567 100644 --- a/clippy_lints/src/uninit_vec.rs +++ b/clippy_lints/src/uninit_vec.rs @@ -177,7 +177,7 @@ fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt }); } }, - ExprKind::MethodCall(path, [self_expr, _], _) if is_reserve(cx, path, self_expr) => { + ExprKind::MethodCall(path, self_expr, [_], _) if is_reserve(cx, path, self_expr) => { return Some(TargetVec { location: VecLocation::Expr(self_expr), init_kind: None, @@ -211,7 +211,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt } }); match expr.kind { - ExprKind::MethodCall(path, [self_expr, _], _) => { + ExprKind::MethodCall(path, self_expr, [_], _) => { let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs(); if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" { Some((self_expr, expr.span)) diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index b0fce91abeb7d..c0a4f3fbacd64 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -144,11 +144,12 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if let ExprKind::MethodCall(_, args, _) = expr.kind { + if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind { let arg_indices = get_args_to_check(cx, expr); + let args = std::iter::once(receiver).chain(args.iter()).collect::>(); for (i, trait_name) in arg_indices { if i < args.len() { - match check_arg(cx, &args[i]) { + match check_arg(cx, args[i]) { Some((span, None)) => { span_lint( cx, diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index aec028d5c4824..35824b03170af 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -128,7 +128,7 @@ fn needs_inferred_result_ty( locals_to_check: &mut Vec, seen_locals: &mut HirIdSet, ) -> bool { - let (id, args) = match e.kind { + let (id, receiver, args) = match e.kind { ExprKind::Call( Expr { kind: ExprKind::Path(ref path), @@ -137,11 +137,11 @@ fn needs_inferred_result_ty( }, args, ) => match cx.qpath_res(path, *hir_id) { - Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, args), + Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, None, args), _ => return false, }, - ExprKind::MethodCall(_, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) { - Some(id) => (id, args), + ExprKind::MethodCall(_, receiver, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) { + Some(id) => (id, Some(receiver), args), None => return false, }, ExprKind::Path(QPath::Resolved(None, path)) => { @@ -156,6 +156,11 @@ fn needs_inferred_result_ty( }; let sig = cx.tcx.fn_sig(id).skip_binder(); if let ty::Param(output_ty) = *sig.output().kind() { + let args: Vec<&Expr<'_>> = if let Some(receiver) = receiver { + std::iter::once(receiver).chain(args.iter()).collect() + } else { + args.iter().collect() + }; sig.inputs().iter().zip(args).all(|(&ty, arg)| { !ty.is_param(output_ty.index) || each_value_source_needs_inference(cx, arg, locals_to_check, seen_locals) }) diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index 16da2f11b81a6..a6f777abc6e94 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -30,26 +30,27 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { } } - match expr.kind { - ExprKind::Call(_, args) | ExprKind::MethodCall(_, args, _) => { - let args_to_recover = args - .iter() - .filter(|arg| { - if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) { - !matches!( - &arg.kind, - ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..) - ) - } else { - false - } - }) - .collect::>(); - if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) { - lint_unit_args(cx, expr, &args_to_recover); + let args: Vec<_> = match expr.kind { + ExprKind::Call(_, args) => args.iter().collect(), + ExprKind::MethodCall(_, receiver, args, _) => std::iter::once(receiver).chain(args.iter()).collect(), + _ => return, + }; + + let args_to_recover = args + .into_iter() + .filter(|arg| { + if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) { + !matches!( + &arg.kind, + ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..) + ) + } else { + false } - }, - _ => (), + }) + .collect::>(); + if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) { + lint_unit_args(cx, expr, args_to_recover.as_slice()); } } diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index a5afbb8ff9da4..2c40827db0e75 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { // Check if all return expression respect the following condition and collect them. let mut suggs = Vec::new(); - let can_sugg = find_all_ret_expressions(cx, &body.value, |ret_expr| { + let can_sugg = find_all_ret_expressions(cx, body.value, |ret_expr| { if_chain! { if !ret_expr.span.from_expansion(); // Check if a function call. diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 04e2f301bfd88..fb73c386640b4 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -137,12 +137,12 @@ fn insert_necessary_parens(pat: &mut P) { struct Visitor; impl MutVisitor for Visitor { fn visit_pat(&mut self, pat: &mut P) { - use ast::{BindingMode::*, Mutability::*}; + use ast::BindingAnnotation; noop_visit_pat(pat, self); let target = match &mut pat.kind { // `i @ a | b`, `box a | b`, and `& mut? a | b`. Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p, - Ref(p, Not) if matches!(p.kind, Ident(ByValue(Mut), ..)) => p, // `&(mut x)` + Ref(p, Mutability::Not) if matches!(p.kind, Ident(BindingAnnotation::MUT, ..)) => p, // `&(mut x)` _ => return, }; target.kind = Paren(P(take_pat(target))); diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 323cf83ffcffa..b38d71784fcfc 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { check_map_error(cx, res, expr); } }, - hir::ExprKind::MethodCall(path, [ref arg_0, ..], _) => match path.ident.as_str() { + hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { check_map_error(cx, arg_0, expr); }, @@ -94,9 +94,9 @@ fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> { fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { let mut call = call; - while let hir::ExprKind::MethodCall(path, args, _) = call.kind { + while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind { if matches!(path.ident.as_str(), "or" | "or_else" | "ok") { - call = &args[0]; + call = receiver; } else { break; } @@ -110,7 +110,7 @@ fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr< } fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) { - if let hir::ExprKind::MethodCall(path, _, _) = call.kind { + if let hir::ExprKind::MethodCall(path, ..) = call.kind { let symbol = path.ident.as_str(); let read_trait = if is_await { match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT) diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index ac73173697e85..cfc181e435b9c 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -149,7 +149,8 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> { ident: method_name_ident, .. }, - [self_arg, remaining_args @ ..], + self_arg, + remaining_args, _, ) => { let method_name = method_name_ident.name.as_str(); diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index d3f9e5abfd739..7e451b7b7a419 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -154,13 +154,13 @@ fn collect_unwrap_info<'tcx>( return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false); } else { if_chain! { - if let ExprKind::MethodCall(method_name, args, _) = &expr.kind; - if let Some(local_id) = path_to_local(&args[0]); - let ty = cx.typeck_results().expr_ty(&args[0]); + if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind; + if let Some(local_id) = path_to_local(receiver); + let ty = cx.typeck_results().expr_ty(receiver); let name = method_name.ident.as_str(); if is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name); then { - assert!(args.len() == 1); + assert!(args.is_empty()); let unwrappable = match name { "is_some" | "is_ok" => true, "is_err" | "is_none" => false, @@ -231,7 +231,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } else { // find `unwrap[_err]()` calls: if_chain! { - if let ExprKind::MethodCall(method_name, [self_arg, ..], _) = expr.kind; + if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind; if let Some(id) = path_to_local(self_arg); if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name); let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name); diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs index b32be238cd55a..46020adcaa2ca 100644 --- a/clippy_lints/src/unwrap_in_result.rs +++ b/clippy_lints/src/unwrap_in_result.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { // check for `expect` if let Some(arglists) = method_chain_args(expr, &["expect"]) { - let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); + let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result) { @@ -93,7 +93,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> { // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { - let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); + let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result) { @@ -114,7 +114,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc typeck_results: cx.tcx.typeck(impl_item.def_id), result: Vec::new(), }; - fpu.visit_expr(&body.value); + fpu.visit_expr(body.value); // if we've found one, lint if !fpu.result.is_empty() { diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index b6738e2891d3e..f1b6463ad0f7c 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } }, - ExprKind::MethodCall(name, .., [recv, ..], _) => { + ExprKind::MethodCall(name, recv, ..) => { if is_trait_method(cx, e, sym::Into) && name.ident.as_str() == "into" { let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(recv); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 429c64ac15641..4003fff27c006 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -6,7 +6,9 @@ use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::LitIntType; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::{ArrayLen, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind}; +use rustc_hir::{ + ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::{Ident, Symbol}; @@ -140,7 +142,7 @@ fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) { check_node(cx, hir_id, |v| { - v.expr(&v.bind("expr", &hir.body(body_id).value)); + v.expr(&v.bind("expr", hir.body(body_id).value)); }); } } @@ -402,10 +404,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.expr(func); self.slice(args, |e| self.expr(e)); }, - ExprKind::MethodCall(method_name, args, _) => { - bind!(self, method_name, args); - kind!("MethodCall({method_name}, {args}, _)"); + ExprKind::MethodCall(method_name, receiver, args, _) => { + bind!(self, method_name, receiver, args); + kind!("MethodCall({method_name}, {receiver}, {args}, _)"); self.ident(field!(method_name.ident)); + self.expr(receiver); self.slice(args, |e| self.expr(e)); }, ExprKind::Tup(elements) => { @@ -595,7 +598,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn body(&self, body_id: &Binding) { - let expr = &self.cx.tcx.hir().body(body_id.value).value; + let expr = self.cx.tcx.hir().body(body_id.value).value; bind!(self, expr); out!("let {expr} = &cx.tcx.hir().body({body_id}).value;"); self.expr(expr); @@ -609,10 +612,16 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { match pat.value.kind { PatKind::Wild => kind!("Wild"), - PatKind::Binding(anno, .., name, sub) => { + PatKind::Binding(ann, _, name, sub) => { bind!(self, name); opt_bind!(self, sub); - kind!("Binding(BindingAnnotation::{anno:?}, _, {name}, {sub})"); + let ann = match ann { + BindingAnnotation::NONE => "NONE", + BindingAnnotation::REF => "REF", + BindingAnnotation::MUT => "MUT", + BindingAnnotation::REF_MUT => "REF_MUT", + }; + kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})"); self.ident(name); sub.if_some(|p| self.pat(p)); }, diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index eb34085a2abf3..17d9a04185767 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -505,7 +505,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { .hir_id(), ), ); - collector.visit_expr(&cx.tcx.hir().body(body_id).value); + collector.visit_expr(cx.tcx.hir().body(body_id).value); } } } @@ -653,7 +653,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { } if_chain! { - if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind; + if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind; let fn_name = path.ident; if let Some(sugg) = self.map.get(fn_name.as_str()); let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); @@ -685,9 +685,8 @@ impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass { let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect(); if_chain! { if let ["expn_data", "outer_expn"] = method_names.as_slice(); - let args = arg_lists[1]; - if args.len() == 1; - let self_arg = &args[0]; + let (self_arg, args)= arg_lists[1]; + if args.is_empty(); let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT); then { @@ -734,30 +733,30 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { if and_then_args.len() == 5; if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind; let body = cx.tcx.hir().body(body); - let only_expr = peel_blocks_with_stmt(&body.value); - if let ExprKind::MethodCall(ps, span_call_args, _) = &only_expr.kind; - if let ExprKind::Path(..) = span_call_args[0].kind; + let only_expr = peel_blocks_with_stmt(body.value); + if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind; + if let ExprKind::Path(..) = recv.kind; then { let and_then_snippets = get_and_then_snippets(cx, and_then_args); let mut sle = SpanlessEq::new(cx).deny_side_effects(); match ps.ident.as_str() { - "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { + "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args)); }, - "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { - let help_snippet = snippet(cx, span_call_args[2].span, r#""...""#); + "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { + let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true); }, - "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { - let note_snippet = snippet(cx, span_call_args[2].span, r#""...""#); + "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { + let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); }, "help" => { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); + let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#); suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false); } "note" => { - let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); + let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#); suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); } _ => (), @@ -798,9 +797,9 @@ fn span_suggestion_snippets<'a, 'hir>( cx: &LateContext<'_>, span_call_args: &'hir [Expr<'hir>], ) -> SpanSuggestionSnippets<'a> { - let help_snippet = snippet(cx, span_call_args[2].span, r#""...""#); - let sugg_snippet = snippet(cx, span_call_args[3].span, ".."); - let applicability_snippet = snippet(cx, span_call_args[4].span, "Applicability::MachineApplicable"); + let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); + let sugg_snippet = snippet(cx, span_call_args[2].span, ".."); + let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable"); SpanSuggestionSnippets { help: help_snippet, @@ -954,7 +953,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option LateLintPass<'tcx> for InvalidPaths { if el_ty.is_str(); let body = cx.tcx.hir().body(body_id); let typeck_results = cx.tcx.typeck_body(body_id); - if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, &body.value); + if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value); let path: Vec<&str> = path.iter().map(|x| { if let Constant::Str(s) = x { s.as_str() @@ -1177,7 +1176,7 @@ impl InterningDefinedSymbol { }; if_chain! { // is a method call - if let ExprKind::MethodCall(_, [item], _) = call.kind; + if let ExprKind::MethodCall(_, item, [], _) = call.kind; if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id); let ty = cx.typeck_results().expr_ty(item); // ...on either an Ident or a Symbol diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index b1148bccc2a28..342f627e38275 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -1145,8 +1145,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { self.add_single_span_suggestion(); } }, - ExprKind::MethodCall(path, arg, _arg_span) => { - let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0])); + ExprKind::MethodCall(path, recv, _, _arg_span) => { + let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv)); if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) { let called_method = path.ident.name.as_str().to_string(); for (method_name, is_multi_part) in &SUGGESTION_DIAGNOSTIC_BUILDER_METHODS { diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs index d77a21d668e61..bd5be0c9d7eda 100644 --- a/clippy_lints/src/vec_init_then_push.rs +++ b/clippy_lints/src/vec_init_then_push.rs @@ -100,7 +100,7 @@ impl VecPushSearcher { || get_parent_expr(cx, last_place) .map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _))); }, - ExprKind::MethodCall(_, [recv, ..], _) + ExprKind::MethodCall(_, recv, ..) if recv.hir_id == e.hir_id && adjusted_mut == Mutability::Mut && !adjusted_ty.peel_refs().is_slice() => @@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { if let Some(init_expr) = local.init - && let PatKind::Binding(BindingAnnotation::Mutable, id, name, None) = local.pat.kind + && let PatKind::Binding(BindingAnnotation::MUT, id, name, None) = local.pat.kind && !in_external_macro(cx.sess(), local.span) && let Some(init) = get_vec_init_kind(cx, init_expr) && !matches!(init, VecInitKind::WithExprCapacity(_)) @@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let Some(searcher) = self.searcher.take() { if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind - && let ExprKind::MethodCall(name, [self_arg, _], _) = expr.kind + && let ExprKind::MethodCall(name, self_arg, [_], _) = expr.kind && path_to_local_id(self_arg, searcher.local_id) && name.ident.as_str() == "push" { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index abd681c53076e..640a09a7a9123 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -526,7 +526,7 @@ impl SimpleFormatArgs { str_lit_span: Span, fmt_span: Span, ) { - use rustc_parse_format::{ArgumentImplicitlyIs, ArgumentIs, CountIsParam}; + use rustc_parse_format::{ArgumentImplicitlyIs, ArgumentIs, CountIsParam, CountIsStar}; let snippet = snippet_opt(cx, fmt_span); @@ -540,7 +540,7 @@ impl SimpleFormatArgs { self.push_to_complex(span, n); }; - if let (CountIsParam(n), Some(span)) = (arg.format.precision, arg.format.precision_span) { + if let (CountIsParam(n) | CountIsStar(n), Some(span)) = (arg.format.precision, arg.format.precision_span) { // We need to do this hack as precision spans should be converted from .* to .foo$ let hack = if snippet.as_ref().and_then(|s| s.find('*')).is_some() { 0 diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 8335ffae81eb7..7a8d4e8068ed6 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -118,9 +118,9 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), ExprKind::Lit(ref lit) => lit_search_pat(&lit.node), ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), - ExprKind::Call(e, []) | ExprKind::MethodCall(_, [e], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), + ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), ExprKind::Call(first, [.., last]) - | ExprKind::MethodCall(_, [first, .., last], _) + | ExprKind::MethodCall(_, first, [.., last], _) | ExprKind::Binary(_, first, last) | ExprKind::Tup([first, .., last]) | ExprKind::Assign(first, last, _) @@ -140,7 +140,7 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { (expr_search_pat(tcx, e).0, Pat::Str("await")) }, - ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, &tcx.hir().body(body).value).1), + ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, tcx.hir().body(body).value).1), ExprKind::Block( Block { rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), @@ -254,7 +254,7 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI let (start_pat, end_pat) = match kind { FnKind::ItemFn(.., header) => (fn_header_search_pat(*header), Pat::Str("")), FnKind::Method(.., sig) => (fn_header_search_pat(sig.header), Pat::Str("")), - FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, &body.value).1), + FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, body.value).1), }; let start_pat = match tcx.hir().get(hir_id) { Node::Item(Item { vis_span, .. }) | Node::ImplItem(ImplItem { vis_span, .. }) => { diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 730724b95b968..91c9c382c236b 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -45,12 +45,7 @@ impl ops::BitOrAssign for EagernessSuggestion { } /// Determine the eagerness of the given function call. -fn fn_eagerness<'tcx>( - cx: &LateContext<'tcx>, - fn_id: DefId, - name: Symbol, - args: &'tcx [Expr<'_>], -) -> EagernessSuggestion { +fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: bool) -> EagernessSuggestion { use EagernessSuggestion::{Eager, Lazy, NoChange}; let name = name.as_str(); @@ -59,7 +54,7 @@ fn fn_eagerness<'tcx>( None => return Lazy, }; - if (name.starts_with("as_") || name == "len" || name == "is_empty") && args.len() == 1 { + if (name.starts_with("as_") || name == "len" || name == "is_empty") && have_one_arg { if matches!( cx.tcx.crate_name(fn_id.krate), sym::std | sym::core | sym::alloc | sym::proc_macro @@ -127,10 +122,11 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS }, Res::Def(_, id) => match path { QPath::Resolved(_, p) => { - self.eagerness |= fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, args); + self.eagerness |= + fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, !args.is_empty()); }, QPath::TypeRelative(_, name) => { - self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, args); + self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty()); }, QPath::LangItem(..) => self.eagerness = Lazy, }, @@ -141,12 +137,12 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS self.eagerness |= NoChange; return; }, - ExprKind::MethodCall(name, args, _) => { + ExprKind::MethodCall(name, ..) => { self.eagerness |= self .cx .typeck_results() .type_dependent_def_id(e.hir_id) - .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, args)); + .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, true)); }, ExprKind::Index(_, e) => { let ty = self.cx.typeck_results().expr_ty_adjusted(e); diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 1834e2a2de872..7dd1a3b7e1938 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHasher; use rustc_hir::def::Res; use rustc_hir::HirIdMap; use rustc_hir::{ - ArrayLen, BinOpKind, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, - HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, - Stmt, StmtKind, Ty, TyKind, TypeBinding, + ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, + GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, + PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; @@ -201,8 +201,8 @@ impl HirEqInterExpr<'_, '_, '_> { self.inner.cx.tcx.typeck_body(right), )); let res = self.eq_expr( - &self.inner.cx.tcx.hir().body(left).value, - &self.inner.cx.tcx.hir().body(right).value, + self.inner.cx.tcx.hir().body(left).value, + self.inner.cx.tcx.hir().body(right).value, ); self.inner.maybe_typeck_results = old_maybe_typeck_results; res @@ -282,8 +282,14 @@ impl HirEqInterExpr<'_, '_, '_> { && self.eq_expr(l.body, r.body) }) }, - (&ExprKind::MethodCall(l_path, l_args, _), &ExprKind::MethodCall(r_path, r_args, _)) => { - self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) + ( + &ExprKind::MethodCall(l_path, l_receiver, l_args, _), + &ExprKind::MethodCall(r_path, r_receiver, r_args, _), + ) => { + self.inner.allow_side_effects + && self.eq_path_segment(l_path, r_path) + && self.eq_expr(l_receiver, r_receiver) + && self.eq_exprs(l_args, r_args) }, (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { self.eq_expr(le, re) && self.eq_array_length(ll, rl) @@ -643,7 +649,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }) => { std::mem::discriminant(&capture_clause).hash(&mut self.s); // closures inherit TypeckResults - self.hash_expr(&self.cx.tcx.hir().body(body).value); + self.hash_expr(self.cx.tcx.hir().body(body).value); }, ExprKind::Field(e, ref f) => { self.hash_expr(e); @@ -743,8 +749,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { s.hash(&mut self.s); }, - ExprKind::MethodCall(path, args, ref _fn_span) => { + ExprKind::MethodCall(path, receiver, args, ref _fn_span) => { self.hash_name(path.ident.name); + self.hash_expr(receiver); self.hash_exprs(args); }, ExprKind::ConstBlock(ref l_id) => { @@ -815,8 +822,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { - PatKind::Binding(ann, _, _, pat) => { - std::mem::discriminant(&ann).hash(&mut self.s); + PatKind::Binding(BindingAnnotation(by_ref, mutability), _, _, pat) => { + std::mem::discriminant(&by_ref).hash(&mut self.s); + std::mem::discriminant(&mutability).hash(&mut self.s); if let Some(pat) = pat { self.hash_pat(pat); } @@ -1002,7 +1010,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_body(&mut self, body_id: BodyId) { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id)); - self.hash_expr(&self.cx.tcx.hir().body(body_id).value); + self.hash_expr(self.cx.tcx.hir().body(body_id).value); self.maybe_typeck_results = old_maybe_typeck_results; } @@ -1010,7 +1018,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for arg in arg_list { match *arg { GenericArg::Lifetime(l) => self.hash_lifetime(l), - GenericArg::Type(ref ty) => self.hash_ty(ty), + GenericArg::Type(ty) => self.hash_ty(ty), GenericArg::Const(ref ca) => self.hash_body(ca.value.body), GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8ab87c48620d2..a1a716ebeca29 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2,6 +2,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(let_else)] +#![feature(let_chains)] #![feature(lint_reasons)] #![feature(once_cell)] #![feature(rustc_private)] @@ -191,7 +192,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< let hir = cx.tcx.hir(); if_chain! { if let Some(Node::Pat(pat)) = hir.find(hir_id); - if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..)); + if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)); let parent = hir.get_parent_node(hir_id); if let Some(Node::Local(local)) = hir.find(parent); then { @@ -336,7 +337,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator Some(ty), + hir::GenericArg::Type(ty) => Some(*ty), _ => None, }) } @@ -1030,26 +1031,26 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' v.allow_closure.then_some(v.captures) } +/// Arguments of a method: the receiver and all the additional arguments. +pub type MethodArguments<'tcx> = Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>; + /// Returns the method names and argument list of nested method call expressions that make up /// `expr`. method/span lists are sorted with the most recent call first. -pub fn method_calls<'tcx>( - expr: &'tcx Expr<'tcx>, - max_depth: usize, -) -> (Vec, Vec<&'tcx [Expr<'tcx>]>, Vec) { +pub fn method_calls<'tcx>(expr: &'tcx Expr<'tcx>, max_depth: usize) -> (Vec, MethodArguments<'tcx>, Vec) { let mut method_names = Vec::with_capacity(max_depth); let mut arg_lists = Vec::with_capacity(max_depth); let mut spans = Vec::with_capacity(max_depth); let mut current = expr; for _ in 0..max_depth { - if let ExprKind::MethodCall(path, args, _) = ¤t.kind { - if args.iter().any(|e| e.span.from_expansion()) { + if let ExprKind::MethodCall(path, receiver, args, _) = ¤t.kind { + if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) { break; } method_names.push(path.ident.name); - arg_lists.push(&**args); + arg_lists.push((*receiver, &**args)); spans.push(path.ident.span); - current = &args[0]; + current = receiver; } else { break; } @@ -1064,18 +1065,18 @@ pub fn method_calls<'tcx>( /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec` /// containing the `Expr`s for /// `.bar()` and `.baz()` -pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option]>> { +pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option, &'a [Expr<'a>])>> { let mut current = expr; let mut matched = Vec::with_capacity(methods.len()); for method_name in methods.iter().rev() { // method chains are stored last -> first - if let ExprKind::MethodCall(path, args, _) = current.kind { + if let ExprKind::MethodCall(path, receiver, args, _) = current.kind { if path.ident.name.as_str() == *method_name { - if args.iter().any(|e| e.span.from_expansion()) { + if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) { return None; } - matched.push(args); // build up `matched` backwards - current = &args[0]; // go to parent expression + matched.push((receiver, args)); // build up `matched` backwards + current = receiver; // go to parent expression } else { return None; } @@ -1238,8 +1239,10 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>( ty_is_fn_once_param(cx.tcx, ty.skip_binder(), predicates).then_some(()) }) }, - ExprKind::MethodCall(_, args, _) => { - let i = args.iter().position(|arg| arg.hir_id == id)?; + ExprKind::MethodCall(_, receiver, args, _) => { + let i = std::iter::once(receiver) + .chain(args.iter()) + .position(|arg| arg.hir_id == id)?; let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?; let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i]; ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(()) @@ -1811,7 +1814,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool } }; - let mut expr = &func.value; + let mut expr = func.value; loop { match expr.kind { #[rustfmt::skip] diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 6b7d5e9aea801..bd89ff977f877 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -646,7 +646,7 @@ impl<'tcx> Count<'tcx> { span, values, )?), - rpf::Count::CountIsParam(_) => { + rpf::Count::CountIsParam(_) | rpf::Count::CountIsStar(_) => { Self::Param(FormatParam::new(FormatParamKind::Numbered, position?, inner?, values)?) }, rpf::Count::CountImplied => Self::Implied, diff --git a/clippy_utils/src/ptr.rs b/clippy_utils/src/ptr.rs index 649b7b9940af3..0226f74906b51 100644 --- a/clippy_utils/src/ptr.rs +++ b/clippy_utils/src/ptr.rs @@ -36,7 +36,7 @@ fn extract_clone_suggestions<'tcx>( if abort { return false; } - if let ExprKind::MethodCall(seg, [recv], _) = expr.kind { + if let ExprKind::MethodCall(seg, recv, [], _) = expr.kind { if path_to_local_id(recv, id) { if seg.ident.name.as_str() == "capacity" { abort = true; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 3bf75bcbee83e..d5f64e5118f56 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -6,8 +6,8 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ - Body, CastKind, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, + Terminator, TerminatorKind, }; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; @@ -55,7 +55,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: body.local_decls.iter().next().unwrap().source_info.span, )?; - for bb in body.basic_blocks() { + for bb in body.basic_blocks.iter() { check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { check_statement(tcx, body, def_id, stmt)?; @@ -212,11 +212,16 @@ fn check_statement<'tcx>( check_place(tcx, **place, span, body) }, - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => { + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body), + + StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + rustc_middle::mir::CopyNonOverlapping { dst, src, count }, + )) => { check_operand(tcx, dst, span, body)?; check_operand(tcx, src, span, body)?; check_operand(tcx, count, span, body) }, + // These are all NOPs StatementKind::StorageLive(_) | StatementKind::StorageDead(_) diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 081c98e2f3ce7..cca71bbf76e28 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -373,12 +373,14 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { | AssocOp::LessEqual | AssocOp::NotEqual | AssocOp::Greater - | AssocOp::GreaterEqual => format!( - "{} {} {}", - lhs, - op.to_ast_binop().expect("Those are AST ops").to_string(), - rhs - ), + | AssocOp::GreaterEqual => { + format!( + "{} {} {}", + lhs, + op.to_ast_binop().expect("Those are AST ops").to_string(), + rhs + ) + }, AssocOp::Assign => format!("{} = {}", lhs, rhs), AssocOp::AssignOp(op) => { format!("{} {}= {}", lhs, token_kind_to_string(&token::BinOp(op)), rhs) @@ -868,15 +870,15 @@ impl<'tcx> DerefDelegate<'_, 'tcx> { /// indicates whether the function from `parent_expr` takes its args by double reference fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool { let ty = match parent_expr.kind { - ExprKind::MethodCall(_, call_args, _) => { + ExprKind::MethodCall(_, receiver, call_args, _) => { if let Some(sig) = self .cx .typeck_results() .type_dependent_def_id(parent_expr.hir_id) .map(|did| self.cx.tcx.fn_sig(did).skip_binder()) { - call_args - .iter() + std::iter::once(receiver) + .chain(call_args.iter()) .position(|arg| arg.hir_id == cmt_hir_id) .map(|i| sig.inputs()[i]) } else { @@ -933,14 +935,14 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { match &parent_expr.kind { // given expression is the self argument and will be handled completely by the compiler // i.e.: `|x| x.is_something()` - ExprKind::MethodCall(_, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => { + ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => { let _ = write!(self.suggestion_start, "{}{}", start_snip, ident_str_with_proj); self.next_pos = span.hi(); return; }, // item is used in a call // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)` - ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, [_, call_args @ ..], _) => { + ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => { let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id); let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind(); diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index bae8ad9f56590..232d571902b6c 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -274,7 +274,7 @@ pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool { } !found }) - .visit_expr(&cx.tcx.hir().body(body).value); + .visit_expr(cx.tcx.hir().body(body).value); found } @@ -568,6 +568,7 @@ pub fn for_each_local_use_after_expr<'tcx, B>( // Calls the given function for every unconsumed temporary created by the expression. Note the // function is only guaranteed to be called for types which need to be dropped, but it may be called // for other types. +#[allow(clippy::too_many_lines)] pub fn for_each_unconsumed_temporary<'tcx, B>( cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>, @@ -620,7 +621,13 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( helper(typeck, true, arg, f)?; } }, - ExprKind::MethodCall(_, args, _) | ExprKind::Tup(args) | ExprKind::Array(args) => { + ExprKind::MethodCall(_, receiver, args, _) => { + helper(typeck, true, receiver, f)?; + for arg in args { + helper(typeck, true, arg, f)?; + } + }, + ExprKind::Tup(args) | ExprKind::Array(args) => { for arg in args { helper(typeck, true, arg, f)?; } diff --git a/rust-toolchain b/rust-toolchain index 85b60fefd60fc..b6976366dafc9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-08-27" +channel = "nightly-2022-09-08" components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/tests/ui/author.stdout b/tests/ui/author.stdout index 3125863036bb7..597318a556b85 100644 --- a/tests/ui/author.stdout +++ b/tests/ui/author.stdout @@ -6,7 +6,7 @@ if_chain! { if match_qpath(qpath, &["char"]); if let ExprKind::Lit(ref lit) = expr.kind; if let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind; if name.as_str() == "x"; then { // report your lint here diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout index 2fc4a7d1f7fe8..a529981e2e683 100644 --- a/tests/ui/author/blocks.stdout +++ b/tests/ui/author/blocks.stdout @@ -5,13 +5,13 @@ if_chain! { if let Some(init) = local.init; if let ExprKind::Lit(ref lit) = init.kind; if let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind; if name.as_str() == "x"; if let StmtKind::Local(local1) = block.stmts[1].kind; if let Some(init1) = local1.init; if let ExprKind::Lit(ref lit1) = init1.kind; if let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local1.pat.kind; if name1.as_str() == "_t"; if let StmtKind::Semi(e) = block.stmts[2].kind; if let ExprKind::Unary(UnOp::Neg, inner) = e.kind; @@ -31,7 +31,7 @@ if_chain! { if let ExprKind::Path(ref qpath) = func.kind; if match_qpath(qpath, &["String", "new"]); if args.is_empty(); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind; if name.as_str() == "expr"; if let Some(trailing_expr) = block.expr; if let ExprKind::Call(func1, args1) = trailing_expr.kind; diff --git a/tests/ui/author/loop.stdout b/tests/ui/author/loop.stdout index 3d9560f697a79..ceb53fcd49636 100644 --- a/tests/ui/author/loop.stdout +++ b/tests/ui/author/loop.stdout @@ -1,6 +1,6 @@ if_chain! { if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind; if name.as_str() == "y"; if let ExprKind::Struct(qpath, fields, None) = arg.kind; if matches!(qpath, QPath::LangItem(LangItem::Range, _)); @@ -17,7 +17,7 @@ if_chain! { if let Some(init) = local.init; if let ExprKind::Path(ref qpath1) = init.kind; if match_qpath(qpath1, &["y"]); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind; if name1.as_str() == "z"; if block.expr.is_none(); then { diff --git a/tests/ui/author/matches.stdout b/tests/ui/author/matches.stdout index 38444a0094ca9..2cf69a035b4c7 100644 --- a/tests/ui/author/matches.stdout +++ b/tests/ui/author/matches.stdout @@ -21,7 +21,7 @@ if_chain! { if let Some(init1) = local1.init; if let ExprKind::Lit(ref lit4) = init1.kind; if let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local1.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local1.pat.kind; if name.as_str() == "x"; if let Some(trailing_expr) = block.expr; if let ExprKind::Path(ref qpath) = trailing_expr.kind; @@ -30,7 +30,7 @@ if_chain! { if arms[2].guard.is_none(); if let ExprKind::Lit(ref lit5) = arms[2].body.kind; if let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind; + if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind; if name1.as_str() == "a"; then { // report your lint here diff --git a/tests/ui/author/struct.stdout b/tests/ui/author/struct.stdout index 5e78b7c9de7e3..b5bbc9e213c6e 100644 --- a/tests/ui/author/struct.stdout +++ b/tests/ui/author/struct.stdout @@ -53,11 +53,11 @@ if_chain! { } } if_chain! { - if let ExprKind::MethodCall(method_name, args, _) = expr.kind; + if let ExprKind::MethodCall(method_name, receiver, args, _) = expr.kind; if method_name.ident.as_str() == "test"; - if args.len() == 1; - if let ExprKind::Path(ref qpath) = args[0].kind; + if let ExprKind::Path(ref qpath) = receiver.kind; if match_qpath(qpath, &["test_method_call"]); + if args.is_empty(); then { // report your lint here } diff --git a/tests/ui/indexing_slicing_index.rs b/tests/ui/indexing_slicing_index.rs index 45a430edcb589..7ebf6ee993cbd 100644 --- a/tests/ui/indexing_slicing_index.rs +++ b/tests/ui/indexing_slicing_index.rs @@ -3,7 +3,7 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(const_err, clippy::no_effect, clippy::unnecessary_operation)] +#![allow(const_err, unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)] const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr. diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index 4c98e1827bdbb..fee8e3030b808 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![feature(let_chains)] #![allow( unused, clippy::assign_op_pattern, diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index 25e1e0214fb44..402d9f9ef7f81 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -1,4 +1,5 @@ // run-rustfix +#![feature(let_chains)] #![allow( unused, clippy::assign_op_pattern, diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index 97f0f7019a9df..313cdbbeba183 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -1,5 +1,5 @@ error: unneeded late initialization - --> $DIR/needless_late_init.rs:22:5 + --> $DIR/needless_late_init.rs:23:5 | LL | let a; | ^^^^^^ created here @@ -13,7 +13,7 @@ LL | let a = "zero"; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:25:5 + --> $DIR/needless_late_init.rs:26:5 | LL | let b; | ^^^^^^ created here @@ -27,7 +27,7 @@ LL | let b = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:26:5 + --> $DIR/needless_late_init.rs:27:5 | LL | let c; | ^^^^^^ created here @@ -41,7 +41,7 @@ LL | let c = 2; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:30:5 + --> $DIR/needless_late_init.rs:31:5 | LL | let d: usize; | ^^^^^^^^^^^^^ created here @@ -54,7 +54,7 @@ LL | let d: usize = 1; | ~~~~~~~~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:33:5 + --> $DIR/needless_late_init.rs:34:5 | LL | let e; | ^^^^^^ created here @@ -67,7 +67,7 @@ LL | let e = format!("{}", d); | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:38:5 + --> $DIR/needless_late_init.rs:39:5 | LL | let a; | ^^^^^^ @@ -88,7 +88,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:47:5 + --> $DIR/needless_late_init.rs:48:5 | LL | let b; | ^^^^^^ @@ -109,7 +109,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:54:5 + --> $DIR/needless_late_init.rs:55:5 | LL | let d; | ^^^^^^ @@ -130,7 +130,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:62:5 + --> $DIR/needless_late_init.rs:63:5 | LL | let e; | ^^^^^^ @@ -151,7 +151,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:69:5 + --> $DIR/needless_late_init.rs:70:5 | LL | let f; | ^^^^^^ @@ -167,7 +167,7 @@ LL + 1 => "three", | error: unneeded late initialization - --> $DIR/needless_late_init.rs:75:5 + --> $DIR/needless_late_init.rs:76:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:83:5 + --> $DIR/needless_late_init.rs:84:5 | LL | let x; | ^^^^^^ created here @@ -201,7 +201,7 @@ LL | let x = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:87:5 + --> $DIR/needless_late_init.rs:88:5 | LL | let x; | ^^^^^^ created here @@ -215,7 +215,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:91:5 + --> $DIR/needless_late_init.rs:92:5 | LL | let x; | ^^^^^^ created here @@ -229,7 +229,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:110:5 + --> $DIR/needless_late_init.rs:111:5 | LL | let a; | ^^^^^^ @@ -250,7 +250,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:127:5 + --> $DIR/needless_late_init.rs:128:5 | LL | let a; | ^^^^^^ diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs index dac5ce272c026..2113173170868 100644 --- a/tests/ui/uninit.rs +++ b/tests/ui/uninit.rs @@ -1,5 +1,5 @@ #![feature(stmt_expr_attributes)] -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, invalid_value)] use std::mem::{self, MaybeUninit};