diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 62c73dbac48b..aa431f0596cc 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -1,8 +1,7 @@ use crate::consts::{constant, Constant}; use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help}; use if_chain::if_chain; -use rustc_ast::ast::LitKind; -use rustc_hir::{Expr, ExprKind, PatKind, UnOp}; +use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -102,31 +101,22 @@ enum AssertKind { /// Check if the expression matches /// /// ```rust,ignore -/// match { let _t = !c; _t } { -/// true => { -/// { -/// ::std::rt::begin_panic(message, _) -/// } -/// } -/// _ => { } -/// }; +/// if !c { +/// { +/// ::std::rt::begin_panic(message, _) +/// } +/// } /// ``` /// /// where `message` is any expression and `c` is a constant bool. fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { if_chain! { - if let ExprKind::Match(ref expr, ref arms, _) = expr.kind; - // matches { let _t = expr; _t } - if let ExprKind::DropTemps(ref expr) = expr.kind; - if let ExprKind::Unary(UnOp::UnNot, ref expr) = expr.kind; + if let ExprKind::If(ref cond, ref then, _) = expr.kind; + if let ExprKind::Unary(UnOp::UnNot, ref expr) = cond.kind; // bind the first argument of the `assert!` macro if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr); - // arm 1 pattern - if let PatKind::Lit(ref lit_expr) = arms[0].pat.kind; - if let ExprKind::Lit(ref lit) = lit_expr.kind; - if let LitKind::Bool(true) = lit.node; - // arm 1 block - if let ExprKind::Block(ref block, _) = arms[0].body.kind; + // block + if let ExprKind::Block(ref block, _) = then.kind; if block.stmts.is_empty(); if let Some(block_expr) = &block.expr; // inner block is optional. unwrap it if it exists, or use the expression as is otherwise. diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs index 736730d4084f..4efca10bcdf1 100644 --- a/clippy_lints/src/blocks_in_if_conditions.rs +++ b/clippy_lints/src/blocks_in_if_conditions.rs @@ -1,4 +1,4 @@ -use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg}; +use crate::utils::{differing_macro_contexts, snippet_block_with_applicability, span_lint, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BlockCheckMode, Expr, ExprKind}; @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions { if in_external_macro(cx.sess(), expr.span) { return; } - if let Some((cond, _, _)) = higher::if_block(&expr) { + if let ExprKind::If(cond, _, _) = &expr.kind { if let ExprKind::Block(block, _) = &cond.kind { if block.rules == BlockCheckMode::DefaultBlock { if block.stmts.is_empty() { diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index b1bc2ec29e16..b3ebdf4ca30d 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -147,6 +147,9 @@ impl<'tcx> Visitor<'tcx> for CCHelper { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { walk_expr(self, e); match e.kind { + ExprKind::If(_, _, _) => { + self.cc += 1; + }, ExprKind::Match(_, ref arms, _) => { if arms.len() > 1 { self.cc += 1; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 0035ded9356c..166eadf86c17 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,6 +1,6 @@ #![allow(clippy::float_cmp)] -use crate::utils::{clip, higher, sext, unsext}; +use crate::utils::{clip, sext, unsext}; use if_chain::if_chain; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; @@ -228,9 +228,6 @@ pub struct ConstEvalLateContext<'a, 'tcx> { impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr<'_>) -> Option { - if let Some((ref cond, ref then, otherwise)) = higher::if_block(&e) { - return self.ifthenelse(cond, then, otherwise); - } match e.kind { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), ExprKind::Block(ref block, _) => self.block(block), @@ -249,6 +246,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { UnOp::UnNeg => self.constant_negate(&o, self.typeck_results.expr_ty(e)), UnOp::UnDeref => Some(if let Constant::Ref(r) = o { *r } else { o }), }), + ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right), ExprKind::Call(ref callee, ref args) => { // We only handle a few const functions for now. diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 46ce92ea6d78..944aaafb46de 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,6 +1,6 @@ use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash}; -use crate::utils::{get_parent_expr, higher, if_sequence, span_lint_and_note}; -use rustc_hir::{Block, Expr}; +use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note}; +use rustc_hir::{Block, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -109,11 +109,13 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() { // skip ifs directly in else, it will be checked in the parent if - if let Some(expr) = get_parent_expr(cx, expr) { - if let Some((_, _, Some(ref else_expr))) = higher::if_block(&expr) { - if else_expr.hir_id == expr.hir_id { - return; - } + if let Some(&Expr { + kind: ExprKind::If(_, _, Some(ref else_expr)), + .. + }) = get_parent_expr(cx, expr) + { + if else_expr.hir_id == expr.hir_id { + return; } } diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 349402453226..48899b338993 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,5 +1,5 @@ use crate::utils::{is_copy, match_path, paths, span_lint_and_note}; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -33,10 +33,10 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'tcx> LateLintPass<'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl { + if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), .. - } = item.kind + }) = item.kind { let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id)); diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index c75efc6e99f8..b1e363663bb2 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -7,7 +7,7 @@ use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{ - BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety, + BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; @@ -164,10 +164,10 @@ declare_lint_pass!(Derive => [ impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl { + if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), .. - } = item.kind + }) = item.kind { let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id)); let is_automatically_derived = is_automatically_derived(&*item.attrs); diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index aba655327959..f518da55cd76 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -182,11 +182,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); } }, - hir::ItemKind::Impl { - of_trait: ref trait_ref, - .. - } => { - self.in_trait_impl = trait_ref.is_some(); + hir::ItemKind::Impl(ref impl_) => { + self.in_trait_impl = impl_.of_trait.is_some(); }, _ => {}, } diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 35a5d00f4aa5..37948e06869c 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,5 +1,5 @@ use crate::utils::SpanlessEq; -use crate::utils::{get_item_name, higher, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt}; +use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt}; use crate::utils::{snippet_with_applicability, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; @@ -54,7 +54,7 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]); impl<'tcx> LateLintPass<'tcx> for HashMapPass { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some((ref check, ref then_block, ref else_block)) = higher::if_block(&expr) { + if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.kind { if let ExprKind::Unary(UnOp::UnNot, ref check) = check.kind { if let Some((ty, map, key)) = check_cond(cx, check) { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 9fcd17a756a3..40e93da8dffb 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,5 +1,5 @@ use rustc_hir::intravisit; -use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, ItemKind, Node}; +use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, TraitRef, Ty}; @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { let mut trait_self_ty = None; if let Some(Node::Item(item)) = parent_node { // If the method is an impl for a trait, don't warn. - if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind { + if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = item.kind { return; } @@ -181,7 +181,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) { self.set.insert(cmt.hir_id); } - return; } } } diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 509a4a4e15f6..9f389c8d2f9e 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -57,11 +57,11 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { // check for `impl From for ..` let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id); if_chain! { - if let hir::ItemKind::Impl{ items: impl_items, .. } = item.kind; + if let hir::ItemKind::Impl(impl_) = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT); then { - lint_impl_body(cx, item.span, impl_items); + lint_impl_body(cx, item.span, impl_.items); } } } diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 18fea8b34bfd..ffef78aac806 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,7 +2,7 @@ use crate::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; -use crate::utils::{eq_expr_value, get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg}; +use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; @@ -556,11 +556,11 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let Some((cond, body, Some(else_body))) = higher::if_block(&expr); + if let ExprKind::If(cond, body, else_body) = expr.kind; if let ExprKind::Block(block, _) = body.kind; if block.stmts.is_empty(); if let Some(if_body_expr) = block.expr; - if let ExprKind::Block(else_block, _) = else_body.kind; + if let Some(ExprKind::Block(else_block, _)) = else_body.map(|el| &el.kind); if else_block.stmts.is_empty(); if let Some(else_body_expr) = else_block.expr; if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr); diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 03e95c9e27f6..109d90ff772b 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -81,6 +81,13 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) { lint(cx, expr.span, break_expr.span, LINT_BREAK); } }, + ExprKind::If(.., if_expr, else_expr) => { + expr_match(cx, if_expr); + + if let Some(else_expr) = else_expr { + expr_match(cx, else_expr); + } + }, ExprKind::Match(.., arms, source) => { let check_all_arms = match source { MatchSource::IfLetDesugar { diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 3a01acd8fdc9..16e162badb5e 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,4 +1,4 @@ -use crate::utils::{higher, in_macro, match_qpath, span_lint_and_sugg, SpanlessEq}; +use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -42,7 +42,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { return; } if_chain! { - if let Some((ref cond, ref then, None)) = higher::if_block(&expr); + if let ExprKind::If(cond, then, None) = &expr.kind; // Check if the conditional expression is a binary operation if let ExprKind::Binary(ref cond_op, ref cond_left, ref cond_right) = cond.kind; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 4e6bb6047854..ea26c84cde16 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -2,7 +2,7 @@ use crate::utils::{in_macro, span_lint_and_then}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{def_id, Crate, Item, ItemKind}; +use rustc_hir::{def_id, Crate, Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; @@ -49,11 +49,11 @@ impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]); impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl { + if let ItemKind::Impl(Impl { ref generics, of_trait: None, .. - } = item.kind + }) = item.kind { // Remember for each inherent implementation encountered its span and generics // but filter out implementations that have generic params (type or lifetime) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 6fe533510904..e95caf6a35f9 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -3,7 +3,7 @@ use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef}; +use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, Impl, ImplItemRef, Item, ItemKind, TraitItemRef}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -115,11 +115,11 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { match item.kind { ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items), - ItemKind::Impl { + ItemKind::Impl(Impl { of_trait: None, items: ref impl_items, .. - } => check_impl_items(cx, item, impl_items), + }) => check_impl_items(cx, item, impl_items), _ => (), } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 0d2d95324c4f..db717cd1240a 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,5 +1,4 @@ -use crate::utils::visitors::LocalUsedVisitor; -use crate::utils::{higher, qpath_res, snippet, span_lint_and_then}; +use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -64,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { if let hir::StmtKind::Local(ref local) = stmt.kind; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; if let hir::StmtKind::Expr(ref if_) = expr.kind; - if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_); + if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.kind; if !LocalUsedVisitor::new(canonical_id).check_expr(cond); if let hir::ExprKind::Block(ref then, _) = then.kind; if let Some(value) = check_assign(cx, canonical_id, &*then); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a6413dc2662a..1c5ab2874b04 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -742,6 +742,14 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { // Break can come from the inner loop so remove them. absorb_break(&never_loop_block(b, main_loop_id)) }, + ExprKind::If(ref e, ref e2, ref e3) => { + let e1 = never_loop_expr(e, main_loop_id); + let e2 = never_loop_expr(e2, main_loop_id); + let e3 = e3 + .as_ref() + .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); + combine_seq(e1, combine_branches(e2, e3)) + }, ExprKind::Match(ref e, ref arms, _) => { let e = never_loop_expr(e, main_loop_id); if arms.is_empty() { @@ -2594,7 +2602,7 @@ fn is_loop(expr: &Expr<'_>) -> bool { } fn is_conditional(expr: &Expr<'_>) -> bool { - matches!(expr.kind, ExprKind::Match(..)) + matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..)) } fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 3c4368a3545a..a0cfe145a301 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { } if_chain! { - if let Some((cond, then, _)) = higher::if_block(&expr); + if let ExprKind::If(cond, then, _) = &expr.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; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f13f2491d6e9..79aec928d298 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1626,7 +1626,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let self_ty = cx.tcx.type_of(def_id); // if this impl block implements a trait, lint in trait definition instead - if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind { + if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return; } @@ -2048,6 +2048,7 @@ fn lint_expect_fun_call( hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) // These variants are debatable or require further examination + | hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Block{ .. } => true, _ => false, diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index d082a88cd2db..d98e6160d308 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -90,6 +90,12 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc } (found_mapping, found_filtering) }, + // There must be an else_arm or there will be a type error + hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => { + let if_check = check_expression(cx, arg_id, if_arm); + let else_check = check_expression(cx, arg_id, else_arm); + (if_check.0 | else_check.0, if_check.1 | else_check.1) + }, hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), _ => (true, true), } diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 42f97b2ac497..d795f1264579 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,9 +3,7 @@ //! This lint is **warn** by default use crate::utils::sugg::Sugg; -use crate::utils::{ - higher, is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg, -}; +use crate::utils::{is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; @@ -71,7 +69,7 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); impl<'tcx> LateLintPass<'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use self::Expression::{Bool, RetBool}; - if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) { + if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.kind { let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 1984942a9145..c8f89f8046c8 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -8,7 +8,7 @@ use rustc_ast::ast::Attribute; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind}; +use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, TypeFoldable}; @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { if matches!( item.kind, - ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..) + ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) ) { return; } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 68fdd0eb269e..bd3dac663fe2 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -60,9 +60,9 @@ impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]); impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { #[allow(clippy::too_many_lines)] fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - if let hir::ItemKind::Impl { + if let hir::ItemKind::Impl(hir::Impl { of_trait: None, items, .. - } = item.kind + }) = item.kind { for assoc_item in items { if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 6b0d198edcff..3a9aa6ced03b 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -7,7 +7,7 @@ use std::ptr; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ - BodyId, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp, + BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp, }; use rustc_infer::traits::specialization_graph; use rustc_lint::{LateContext, LateLintPass, Lint}; @@ -275,10 +275,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { let item = cx.tcx.hir().expect_item(item_hir_id); match &item.kind { - ItemKind::Impl { + ItemKind::Impl(Impl { of_trait: Some(of_trait_ref), .. - } => { + }) => { if_chain! { // Lint a trait impl item only when the definition is a generic type, // assuming a assoc const is not meant to be a interior mutable type. @@ -317,7 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } } }, - ItemKind::Impl { of_trait: None, .. } => { + ItemKind::Impl(Impl { of_trait: None, .. }) => { let ty = hir_ty_to_ty(cx.tcx, hir_ty); // Normalize assoc types originated from generic params. let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 58c00541af73..7bdf975ffd44 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -109,25 +109,30 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { /// it in curly braces. Otherwise, we don't. fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { + let mut should_wrap = false; + if let Some(Expr { kind: ExprKind::Match( _, arms, - MatchSource::IfDesugar { - contains_else_clause: true, - } - | MatchSource::IfLetDesugar { + MatchSource::IfLetDesugar { contains_else_clause: true, }, ), .. }) = parent.expr { - expr.hir_id == arms[1].body.hir_id - } else { - false + should_wrap = expr.hir_id == arms[1].body.hir_id; + } else if let Some(Expr { + kind: ExprKind::If(_, _, Some(else_clause)), + .. + }) = parent.expr + { + should_wrap = expr.hir_id == else_clause.hir_id; } + + should_wrap }) } diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index ceecc8dbc06f..ed314937ce8b 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,6 +1,6 @@ use crate::utils::{is_automatically_derived, span_lint_hir}; use if_chain::if_chain; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -34,7 +34,7 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { - if let ItemKind::Impl{ of_trait: Some(ref trait_ref), items: impl_items, .. } = item.kind; + if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind; if !is_automatically_derived(&*item.attrs); if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); if trait_ref.path.res.def_id() == eq_trait; diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index c9d9e02717ca..d96a9b025f08 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -6,7 +6,7 @@ use rustc_ast::attr; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node, PatKind}; +use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { if matches!( item.kind, - ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..) + ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) ) { return; } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index c494a7136313..c6329a1381c9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -8,8 +8,8 @@ use crate::utils::{ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ - BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, - Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, + BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item, + ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -132,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { if let ImplItemKind::Fn(ref sig, body_id) = item.kind { let parent_item = cx.tcx.hir().get_parent_item(item.hir_id); if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) { - if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind { + if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = it.kind { return; // ignore trait impls } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index b91233ac5828..6c480d48c756 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,7 +8,7 @@ use rustc_span::sym; use crate::utils::sugg::Sugg; use crate::utils::{ - eq_expr_value, higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, + eq_expr_value, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, span_lint_and_sugg, }; @@ -50,7 +50,7 @@ impl QuestionMark { /// If it matches, it will suggest to use the question mark operator instead fn check_is_none_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let Some((if_expr, body, else_)) = higher::if_block(&expr); + if let ExprKind::If(if_expr, body, else_) = &expr.kind; if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind; if segment.ident.name == sym!(is_none); if Self::expression_returns_none(cx, body); diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 7f4913a02cbd..63548d8fdb43 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -184,6 +184,14 @@ fn check_final_expr<'tcx>( ExprKind::Block(ref block, _) => { check_block_return(cx, block); }, + ExprKind::If(_, then, else_clause_opt) => { + if let ExprKind::Block(ref ifblock, _) = then.kind { + check_block_return(cx, ifblock); + } + if let Some(else_clause) = else_clause_opt { + check_final_expr(cx, else_clause, None, RetReplacement::Empty); + } + }, // a match expr, check all arms // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways @@ -194,10 +202,7 @@ fn check_final_expr<'tcx>( check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); } }, - MatchSource::IfDesugar { - contains_else_clause: true, - } - | MatchSource::IfLetDesugar { + MatchSource::IfLetDesugar { contains_else_clause: true, } => { if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { @@ -212,6 +217,9 @@ fn check_final_expr<'tcx>( } fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option, replacement: RetReplacement) { + if ret_span.from_expansion() { + return; + } match inner_span { Some(inner_span) => { if in_external_macro(cx.tcx.sess, inner_span) || inner_span.from_expansion() { diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 339a7cf3bf5d..44e739725c82 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,5 +1,5 @@ use crate::utils::{get_trait_def_id, paths, span_lint}; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -22,11 +22,11 @@ declare_lint_pass!(SerdeAPI => [SERDE_API_MISUSE]); impl<'tcx> LateLintPass<'tcx> for SerdeAPI { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl { + if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items, .. - } = item.kind + }) = item.kind { let did = trait_ref.path.res.def_id(); if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 4ae22468f78c..24da056770c9 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -333,6 +333,13 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut check_expr(cx, e, bindings) } }, + ExprKind::If(ref cond, ref then, ref otherwise) => { + check_expr(cx, cond, bindings); + check_expr(cx, &**then, bindings); + if let Some(ref o) = *otherwise { + check_expr(cx, o, bindings); + } + }, ExprKind::Match(ref init, arms, _) => { check_expr(cx, init, bindings); let len = bindings.len(); diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs index 006d7a3a12d9..c53727ba1600 100644 --- a/clippy_lints/src/to_string_in_display.rs +++ b/clippy_lints/src/to_string_in_display.rs @@ -1,7 +1,7 @@ use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint}; use if_chain::if_chain; use rustc_hir::def::Res; -use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind}; +use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -111,7 +111,7 @@ impl LateLintPass<'_> for ToStringInDisplay { fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if_chain! { - if let ItemKind::Impl { of_trait: Some(trait_ref), .. } = &item.kind; + if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind; if let Some(did) = trait_ref.trait_def_id(); then { match_def_path(cx, did, &paths::DISPLAY_TRAIT) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ef199c11e271..3b5a83d2a0be 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -260,7 +260,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { // Skip trait implementations; see issue #605. if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) { - if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind { + if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return; } } @@ -2572,21 +2572,16 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } match item.kind { - ItemKind::Impl { - ref generics, - self_ty: ref ty, - ref items, - .. - } => { + ItemKind::Impl(ref impl_) => { let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(ty); + vis.visit_ty(impl_.self_ty); for target in &vis.found { if differing_macro_contexts(item.span, target.span()) { return; } - let generics_suggestion_span = generics.span.substitute_dummy({ + let generics_suggestion_span = impl_.generics.span.substitute_dummy({ let pos = snippet_opt(cx, item.span.until(target.span())) .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); if let Some(pos) = pos { @@ -2597,7 +2592,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { }); let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); - for item in items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) { + for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) { ctr_vis.visit_impl_item(item); } @@ -2610,7 +2605,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { target.type_name() ), move |diag| { - suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis); + suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis); }, ); } diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index 5b9a80f92db6..8ac5dd696b76 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -5,7 +5,7 @@ use crate::utils::{ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, ExprKind, FnDecl, HirId, ItemKind, Node}; +use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { if matches!( item.kind, - ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..) + ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) ) { return; } diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs index da7517125c13..5349c4f7eb8a 100644 --- a/clippy_lints/src/unused_self.rs +++ b/clippy_lints/src/unused_self.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; -use rustc_hir::{HirId, ImplItem, ImplItemKind, ItemKind, Path}; +use rustc_hir::{HirId, Impl, ImplItem, ImplItemKind, ItemKind, Path}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); let assoc_item = cx.tcx.associated_item(def_id); if_chain! { - if let ItemKind::Impl { of_trait: None, .. } = parent_item.kind; + if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; let body = cx.tcx.hir().body(*body_id); diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f4a77e54dd14..b82909eaea60 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,6 +1,5 @@ use crate::utils::{ - differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then, - usage::is_potentially_mutated, + differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated, }; use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; @@ -158,7 +157,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { if in_external_macro(self.cx.tcx.sess, expr.span) { return; } - if let Some((cond, then, els)) = if_block(&expr) { + if let ExprKind::If(cond, then, els) = &expr.kind { walk_expr(self, cond); self.visit_branch(cond, then, false); if let Some(els) = els { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index bb73d66dabac..72d1ca739291 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -181,8 +181,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { return; } if_chain! { - if let ItemKind::Impl{ self_ty: ref item_type, items: refs, .. } = item.kind; - if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.kind; + if let ItemKind::Impl(impl_) = &item.kind; + if let TyKind::Path(QPath::Resolved(_, ref item_path)) = impl_.self_ty.kind; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; let should_check = parameters.as_ref().map_or( @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { let impl_trait_ref = cx.tcx.impl_trait_ref(impl_def_id); if let Some(impl_trait_ref) = impl_trait_ref { - for impl_item_ref in refs { + for impl_item_ref in impl_.items { let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); if let ImplItemKind::Fn(FnSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.kind { @@ -213,7 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } } else { - for impl_item_ref in refs { + for impl_item_ref in impl_.items { let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); visitor.visit_impl_item(impl_item); } diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs index 5aed676fceb2..eac5d0aa3ee9 100644 --- a/clippy_lints/src/utils/ast_utils.rs +++ b/clippy_lints/src/utils/ast_utils.rs @@ -556,7 +556,7 @@ pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts), - (Eq(_, lts), Eq(_, rts)) => lts.eq_unspanned(rts), + (Eq(_, lt), Eq(_, rt)) => lt.kind == rt.kind, _ => false, } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 4249dbb4e651..43afa65de3e5 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -1,7 +1,7 @@ //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -use crate::utils::{get_attr, higher}; +use crate::utils::get_attr; use rustc_ast::ast::{Attribute, LitFloatType, LitKind}; use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashMap; @@ -201,32 +201,6 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { #[allow(clippy::too_many_lines)] fn visit_expr(&mut self, expr: &Expr<'_>) { - // handle if desugarings - // TODO add more desugarings here - if let Some((cond, then, opt_else)) = higher::if_block(&expr) { - let cond_pat = self.next("cond"); - let then_pat = self.next("then"); - if let Some(else_) = opt_else { - let else_pat = self.next("else_"); - println!( - " if let Some((ref {}, ref {}, Some({}))) = higher::if_block(&{});", - cond_pat, then_pat, else_pat, self.current - ); - self.current = else_pat; - self.visit_expr(else_); - } else { - println!( - " if let Some((ref {}, ref {}, None)) = higher::if_block(&{});", - cond_pat, then_pat, self.current - ); - } - self.current = cond_pat; - self.visit_expr(cond); - self.current = then_pat; - self.visit_expr(then); - return; - } - print!(" if let ExprKind::"); let current = format!("{}.kind", self.current); match expr.kind { @@ -351,6 +325,25 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = body_pat; self.visit_block(body); }, + ExprKind::If(ref cond, ref then, ref opt_else) => { + let cond_pat = self.next("cond"); + let then_pat = self.next("then"); + if let Some(ref else_) = *opt_else { + let else_pat = self.next("else_"); + println!( + "If(ref {}, ref {}, Some(ref {})) = {};", + cond_pat, then_pat, else_pat, current + ); + self.current = else_pat; + self.visit_expr(else_); + } else { + println!("If(ref {}, ref {}, None) = {};", cond_pat, then_pat, current); + } + self.current = cond_pat; + self.visit_expr(cond); + self.current = then_pat; + self.visit_expr(then); + }, ExprKind::Match(ref expr, ref arms, desugaring) => { let des = desugaring_name(desugaring); let expr_pat = self.next("expr"); @@ -743,10 +736,6 @@ fn desugaring_name(des: hir::MatchSource) -> String { contains_else_clause ), hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(), - hir::MatchSource::IfDesugar { contains_else_clause } => format!( - "MatchSource::IfDesugar {{ contains_else_clause: {} }}", - contains_else_clause - ), hir::MatchSource::AwaitDesugar => "MatchSource::AwaitDesugar".to_string(), } } diff --git a/clippy_lints/src/utils/eager_or_lazy.rs b/clippy_lints/src/utils/eager_or_lazy.rs index 8fe5ddee1ca8..2f157c5030f4 100644 --- a/clippy_lints/src/utils/eager_or_lazy.rs +++ b/clippy_lints/src/utils/eager_or_lazy.rs @@ -62,6 +62,7 @@ fn identify_some_pure_patterns(expr: &Expr<'_>) -> bool { | ExprKind::Type(..) | ExprKind::DropTemps(..) | ExprKind::Loop(..) + | ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Closure(..) | ExprKind::Block(..) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 01ffac5b5599..9b3585865da3 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -170,33 +170,6 @@ pub fn while_loop<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx hir::Expr< None } -/// Recover the essential nodes of a desugared if block -/// `if cond { then } else { els }` becomes `(cond, then, Some(els))` -pub fn if_block<'tcx>( - expr: &'tcx hir::Expr<'tcx>, -) -> Option<( - &'tcx hir::Expr<'tcx>, - &'tcx hir::Expr<'tcx>, - Option<&'tcx hir::Expr<'tcx>>, -)> { - if let hir::ExprKind::Match(ref cond, ref arms, hir::MatchSource::IfDesugar { contains_else_clause }) = expr.kind { - let cond = if let hir::ExprKind::DropTemps(ref cond) = cond.kind { - cond - } else { - panic!("If block desugar must contain DropTemps"); - }; - let then = &arms[0].body; - let els = if contains_else_clause { - Some(&*arms[1].body) - } else { - None - }; - Some((cond, then, els)) - } else { - None - } -} - /// Represent the pre-expansion arguments of a `vec!` invocation. pub enum VecArgs<'a> { /// `vec![elem; len]` @@ -267,12 +240,11 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option SpanlessEq<'a, 'tcx> { (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => { self.eq_expr(la, ra) && self.eq_expr(li, ri) }, + (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => { + self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r)) + }, (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node, (&ExprKind::Loop(ref lb, ref ll, ref lls), &ExprKind::Loop(ref rb, ref rl, ref rls)) => { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name) @@ -563,6 +566,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(i.ident.name); } }, + ExprKind::If(ref cond, ref then, ref else_opt) => { + let c: fn(_, _, _) -> _ = ExprKind::If; + c.hash(&mut self.s); + self.hash_expr(cond); + self.hash_expr(&**then); + if let Some(ref e) = *else_opt { + self.hash_expr(e); + } + }, ExprKind::Match(ref e, arms, ref s) => { self.hash_expr(e); @@ -743,7 +755,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } for segment in path.segments { segment.ident.name.hash(&mut self.s); - self.hash_generic_args(segment.generic_args().args); + self.hash_generic_args(segment.args().args); } }, QPath::TypeRelative(ref ty, ref segment) => { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 5d946e4bd495..9bec24be9e4e 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -213,6 +213,15 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { hir::ExprKind::Loop(..) => { println!("{}Loop", ind); }, + hir::ExprKind::If(ref cond, _, ref else_opt) => { + println!("{}If", ind); + println!("{}condition:", ind); + print_expr(cx, cond, indent + 1); + if let Some(ref els) = *else_opt { + println!("{}else:", ind); + print_expr(cx, els, indent + 1); + } + }, hir::ExprKind::Match(ref cond, _, ref source) => { println!("{}Match", ind); println!("{}condition:", ind); @@ -423,13 +432,13 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { hir::ItemKind::TraitAlias(..) => { println!("trait alias"); }, - hir::ItemKind::Impl { + hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref _trait_ref), .. - } => { + }) => { println!("trait impl"); }, - hir::ItemKind::Impl { of_trait: None, .. } => { + hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) => { println!("impl"); }, } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 59a1852aba92..7aa17520ba79 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -377,11 +377,11 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { } else if is_expn_of(item.span, "impl_lint_pass").is_some() || is_expn_of(item.span, "declare_lint_pass").is_some() { - if let hir::ItemKind::Impl { + if let hir::ItemKind::Impl(hir::Impl { of_trait: None, items: ref impl_item_refs, .. - } = item.kind + }) = item.kind { let mut collector = LintCollector { output: &mut self.registered_lints, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 27f4cb2b2544..548c4f7510ad 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -439,8 +439,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio if_chain! { if parent_impl != hir::CRATE_HIR_ID; if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl); - if let hir::ItemKind::Impl{ of_trait: trait_ref, .. } = &item.kind; - then { return trait_ref.as_ref(); } + if let hir::ItemKind::Impl(impl_) = &item.kind; + then { return impl_.of_trait.as_ref(); } } None } @@ -1405,7 +1405,7 @@ pub fn if_sequence<'tcx>( let mut conds = SmallVec::new(); let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new(); - while let Some((ref cond, ref then_expr, ref else_expr)) = higher::if_block(&expr) { + while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind { conds.push(&**cond); if let ExprKind::Block(ref block, _) = then_expr.kind { blocks.push(block); @@ -1434,12 +1434,13 @@ pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool { let map = cx.tcx.hir(); let parent_id = map.get_parent_node(expr.hir_id); let parent_node = map.get(parent_id); - - match parent_node { - Node::Expr(e) => higher::if_block(&e).is_some(), - Node::Arm(e) => higher::if_block(&e.body).is_some(), - _ => false, - } + matches!( + parent_node, + Node::Expr(Expr { + kind: ExprKind::If(_, _, _), + .. + }) + ) } // Finds the attribute with the given name, if any @@ -1530,7 +1531,7 @@ pub fn is_no_std_crate(krate: &Crate<'_>) -> bool { /// ``` pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool { if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { - matches!(item.kind, ItemKind::Impl { of_trait: Some(_), .. }) + matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 1fcd41e4dbfe..03678db575f0 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -103,6 +103,7 @@ impl<'a> Sugg<'a> { match expr.kind { hir::ExprKind::AddrOf(..) | hir::ExprKind::Box(..) + | hir::ExprKind::If(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet), diff --git a/clippy_lints/src/utils/visitors.rs b/clippy_lints/src/utils/visitors.rs index 28b3e79d7a6d..ebf69df31ca4 100644 --- a/clippy_lints/src/utils/visitors.rs +++ b/clippy_lints/src/utils/visitors.rs @@ -101,6 +101,13 @@ where } } else { match expr.kind { + hir::ExprKind::If(cond, then, else_opt) => { + self.inside_stmt(true).visit_expr(cond); + self.visit_expr(then); + if let Some(el) = else_opt { + self.visit_expr(el); + } + }, hir::ExprKind::Match(cond, arms, _) => { self.inside_stmt(true).visit_expr(cond); for arm in arms { diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index 1d5fa8d06a99..9761e822a7a0 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -62,7 +62,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues { fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { let parent_id = cx.tcx.hir().get_parent_item(hir_id); if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(parent_id)) { - if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind { + if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return true; } } diff --git a/rust-toolchain b/rust-toolchain index c579beeae89b..72935072f8cd 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-01-02" +channel = "nightly-2021-01-15" components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"] diff --git a/tests/ui/author/if.stdout b/tests/ui/author/if.stdout index c18d035953e5..cac64a3f40b4 100644 --- a/tests/ui/author/if.stdout +++ b/tests/ui/author/if.stdout @@ -1,7 +1,7 @@ if_chain! { if let StmtKind::Local(ref local) = stmt.kind; if let Some(ref init) = local.init; - if let Some((ref cond, ref then, Some(else_))) = higher::if_block(&init); + if let ExprKind::If(ref cond, ref then, Some(ref else_)) = init.kind; if let ExprKind::Block(ref block) = else_.kind; if let Some(trailing_expr) = &block.expr; if block.stmts.len() == 1; diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index d849e093da7b..86bfc5b4bb28 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -86,6 +86,21 @@ fn borrows_but_not_last(value: bool) -> String { } } +macro_rules! needed_return { + ($e:expr) => { + if $e > 3 { + return; + } + }; +} + +fn test_return_in_macro() { + // This will return and the macro below won't be executed. Removing the `return` from the macro + // will change semantics. + needed_return!(10); + needed_return!(0); +} + fn main() { let _ = test_end_of_fn(); let _ = test_no_semicolon(); diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 29f2bd1852af..51061370dfe7 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -86,6 +86,21 @@ fn borrows_but_not_last(value: bool) -> String { } } +macro_rules! needed_return { + ($e:expr) => { + if $e > 3 { + return; + } + }; +} + +fn test_return_in_macro() { + // This will return and the macro below won't be executed. Removing the `return` from the macro + // will change semantics. + needed_return!(10); + needed_return!(0); +} + fn main() { let _ = test_end_of_fn(); let _ = test_no_semicolon(); diff --git a/tests/ui/panic_in_result_fn_assertions.stderr b/tests/ui/panic_in_result_fn_assertions.stderr index 86f61ad718a9..a17f043737d4 100644 --- a/tests/ui/panic_in_result_fn_assertions.stderr +++ b/tests/ui/panic_in_result_fn_assertions.stderr @@ -14,7 +14,7 @@ note: return Err() instead of panicking --> $DIR/panic_in_result_fn_assertions.rs:9:9 | LL | assert!(x == 5, "wrong argument"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index 589b19f68f7a..76b6126c76c6 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -28,10 +28,11 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() { let clippy_minor = clippy_version.minor; let clippy_patch = clippy_version.patch; - // get the rustc version - // this way the rust-toolchain file version is honored + // get the rustc version either from the rustc installed with the toolchain file or from + // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`. + let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string()); let rustc_version = String::from_utf8( - std::process::Command::new("rustc") + std::process::Command::new(&rustc) .arg("--version") .output() .expect("failed to run `rustc --version`")