about summary refs log tree commit diff
path: root/src/tools/clippy
diff options
context:
space:
mode:
authorCaio <c410.f3r@gmail.com>2021-01-01 15:38:11 -0300
committerCaio <c410.f3r@gmail.com>2021-01-07 18:54:12 -0300
commitf85fc264fecf5ab8b16c152dde8a440055323424 (patch)
tree835f4f3a86c2019c5ac18f65c4cfa5de7fd297a4 /src/tools/clippy
parentc8915eebeaaef9f7cc1cff6ffd97f578b03c2ac9 (diff)
downloadrust-f85fc264fecf5ab8b16c152dde8a440055323424.tar.gz
rust-f85fc264fecf5ab8b16c152dde8a440055323424.zip
Reintroduce hir::ExprKind::If
Diffstat (limited to 'src/tools/clippy')
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/consts.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/let_if_seq.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/higher.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/hir_utils.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/sugg.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/visitors.rs7
-rw-r--r--src/tools/clippy/tests/ui/author/if.stdout2
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr2
31 files changed, 152 insertions, 131 deletions
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 62c73dbac48..aa431f0596c 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/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<AssertKind> {
     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/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index 736730d4084..4efca10bcdf 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index b1bc2ec29e1..b3ebdf4ca30 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs
index 0035ded9356..166eadf86c1 100644
--- a/src/tools/clippy/clippy_lints/src/consts.rs
+++ b/src/tools/clippy/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<Constant> {
-        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/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 46ce92ea6d7..6f48ffeb0e9 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/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,12 @@ 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/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 35a5d00f4aa..37948e06869 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 18fea8b34bf..ffef78aac80 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index 03e95c9e27f..109d90ff772 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 3a01acd8fdc..16e162badb5 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 0d2d95324c4..db717cd1240 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs
index 1bd96b2b4c8..281964ee5e8 100644
--- a/src/tools/clippy/clippy_lints/src/loops.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 3c4368a3545..a0cfe145a30 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index e99fe1b97ff..2234890d6e9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -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/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index d082a88cd2d..d98e6160d30 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 76417aa7ed0..71f91eb4bfb 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -90,6 +90,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
                 self.found = true;
                 return;
             },
+            ExprKind::If(..) => {
+                self.found = true;
+                return;
+            },
             ExprKind::Path(_) => {
                 if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
                     if adj
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 42f97b2ac49..6b9a37b5252 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -4,7 +4,7 @@
 
 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,
+    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;
@@ -71,7 +71,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, "<predicate>", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 681dbce9769..391f893ef35 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -109,25 +109,26 @@ 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/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index b91233ac582..6c480d48c75 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 7f4913a02cb..35827e027aa 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/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,9 +202,6 @@ 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 {
                 contains_else_clause: true,
             } => {
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index f8396592678..f2f3dfa09a7 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index f4a77e54dd1..6a87f534369 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -1,5 +1,5 @@
 use crate::utils::{
-    differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then,
+    differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then,
     usage::is_potentially_mutated,
 };
 use if_chain::if_chain;
@@ -158,7 +158,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/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 4249dbb4e65..43afa65de3e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs b/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
index 8fe5ddee1ca..2f157c5030f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/eager_or_lazy.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs
index 01ffac5b559..9b3585865da 100644
--- a/src/tools/clippy/clippy_lints/src/utils/higher.rs
+++ b/src/tools/clippy/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<Vec<&'tcx
 
     if let ExprKind::Block(ref block, _) = e.kind {
         if block.stmts.len() == 1 {
-            if let StmtKind::Semi(ref matchexpr) = block.stmts[0].kind {
+            if let StmtKind::Semi(ref matchexpr) = block.stmts.get(0)?.kind {
                 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
                 if_chain! {
-                    if let ExprKind::Match(ref ifclause, _, _) = matchexpr.kind;
-                    if let ExprKind::DropTemps(ref droptmp) = ifclause.kind;
-                    if let ExprKind::Unary(UnOp::UnNot, condition) = droptmp.kind;
+                    if let ExprKind::If(ref clause, _, _)  = matchexpr.kind;
+                    if let ExprKind::Unary(UnOp::UnNot, condition) = clause.kind;
                     then {
                         return Some(vec![condition]);
                     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index a8fbb2ffaf0..b5cc2bdc463 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -119,6 +119,9 @@ impl<'a, 'tcx> 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.as_str() == r.ident.as_str())
@@ -564,6 +567,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);
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 5d946e4bd49..71c11788d93 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/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);
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 1c68e837c4a..bd103246e4e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -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,11 +1434,11 @@ 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,
+    if let Node::Expr(Expr { kind: ExprKind::If(_, _, _), .. }) = parent_node {
+        true
+    }
+    else {
+        false
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs
index 1fcd41e4dbf..03678db575f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs
+++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/utils/visitors.rs b/src/tools/clippy/clippy_lints/src/utils/visitors.rs
index 28b3e79d7a6..b769a18802b 100644
--- a/src/tools/clippy/clippy_lints/src/utils/visitors.rs
+++ b/src/tools/clippy/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/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index c18d035953e..cac64a3f40b 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/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/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
index 86f61ad718a..a17f043737d 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
+++ b/src/tools/clippy/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`