diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 1f20f5c41fcc..05d3ea6b2748 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -72,7 +72,7 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::If(check, then, _) = &expr.node { + if let Some((check, then, _)) = higher::if_block(&expr) { if let ExprKind::Block(block, _) = &check.node { if block.rules == DefaultBlock { if block.stmts.is_empty() { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 3cdd0f727fb6..c96c7e7e857a 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, sext, unsext}; +use crate::utils::{clip, higher, sext, unsext}; use if_chain::if_chain; use rustc::hir::def::{DefKind, Res}; use rustc::hir::*; @@ -15,7 +15,6 @@ use std::convert::TryFrom; use std::convert::TryInto; use std::hash::{Hash, Hasher}; use syntax::ast::{FloatTy, LitKind}; -use syntax::ptr::P; use syntax_pos::symbol::{LocalInternedString, Symbol}; /// A `LitKind`-like enum to fold constant `Expr`s into. @@ -222,10 +221,12 @@ pub struct ConstEvalLateContext<'a, 'tcx: 'a> { impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// 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.node { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id), ExprKind::Block(ref block, _) => self.block(block), - ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise), ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))), ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec), ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), @@ -358,10 +359,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } - fn ifthenelse(&mut self, cond: &Expr, then: &P, otherwise: &Option>) -> Option { + fn ifthenelse(&mut self, cond: &Expr, then: &Expr, otherwise: Option<&Expr>) -> Option { if let Some(Constant::Bool(b)) = self.expr(cond) { if b { - self.expr(&**then) + self.expr(&*then) } else { otherwise.as_ref().and_then(|expr| self.expr(expr)) } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index d1163e102790..c08d6851aa01 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,4 +1,4 @@ -use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; +use crate::utils::{get_parent_expr, higher, in_macro, snippet, span_lint_and_then, span_note_and_lint}; use crate::utils::{SpanlessEq, SpanlessHash}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -109,13 +109,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if !in_macro(expr.span) { // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr { - node: ExprKind::If(_, _, Some(ref else_expr)), - .. - }) = get_parent_expr(cx, expr) - { - if else_expr.hir_id == expr.hir_id { - return; + 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; + } } } @@ -236,7 +234,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>) let mut conds = SmallVec::new(); let mut blocks: SmallVec<[&Block; 1]> = SmallVec::new(); - while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.node { + while let Some((ref cond, ref then_expr, ref else_expr)) = higher::if_block(&expr) { conds.push(&**cond); if let ExprKind::Block(ref block, _) = then_expr.node { blocks.push(block); diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index c74232a906e1..551e0bb848d8 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, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; +use crate::utils::{get_item_name, higher, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; @@ -41,7 +41,7 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.node { + if let Some((ref check, ref then_block, ref else_block)) = higher::if_block(&expr) { if let ExprKind::Unary(UnOp::UnNot, ref check) = check.node { 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/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 559b0942d2b5..8e0fa1bf2e26 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -74,13 +74,6 @@ impl ImplicitReturn { Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); } }, - ExprKind::If(.., if_expr, else_expr) => { - Self::expr_match(cx, if_expr); - - if let Some(else_expr) = else_expr { - Self::expr_match(cx, else_expr); - } - }, ExprKind::Match(.., arms, source) => { let check_all_arms = match source { MatchSource::IfLetDesugar { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 8a6456925a3d..990d8facd134 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,4 @@ -use crate::utils::{snippet, span_lint_and_then}; +use crate::utils::{higher, snippet, span_lint_and_then}; use if_chain::if_chain; use rustc::hir; use rustc::hir::def::Res; @@ -63,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { if let hir::StmtKind::Local(ref local) = stmt.node; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.node; if let hir::StmtKind::Expr(ref if_) = expr.node; - if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node; + if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_); if !used_in_expr(cx, canonical_id, cond); if let hir::ExprKind::Block(ref then, _) = then.node; 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 362f3ebdf5c4..c67edc00e6b3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -686,14 +686,6 @@ fn never_loop_expr(expr: &Expr, main_loop_id: HirId) -> NeverLoopResult { | ExprKind::Assign(ref e1, ref e2) | ExprKind::AssignOp(_, ref e1, ref e2) | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), 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::Loop(ref b, _, _) => { // Break can come from the inner loop so remove them. absorb_break(&never_loop_block(b, main_loop_id)) @@ -2204,7 +2196,7 @@ fn is_loop(expr: &Expr) -> bool { fn is_conditional(expr: &Expr) -> bool { match expr.node { - ExprKind::If(..) | ExprKind::Match(..) => true, + ExprKind::Match(..) => true, _ => false, } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2e342ee165a3..f8cde663d899 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1266,7 +1266,6 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: 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 fde58b4ff7f0..a28e6fa88bbe 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -89,12 +89,6 @@ fn check_expression<'a, 'tcx: 'a>( (false, false) } }, - // 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::Match(_, ref arms, _) => { let mut found_mapping = false; let mut found_filtering = false; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 94febdbd8a79..0404bc41570f 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use crate::utils::sugg::Sugg; -use crate::utils::{in_macro, span_lint, span_lint_and_sugg}; +use crate::utils::{higher, in_macro, span_lint, span_lint_and_sugg}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; @@ -59,7 +59,7 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use self::Expression::*; - if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node { + if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) { let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "", &mut applicability); @@ -119,7 +119,7 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool let parent_node = cx.tcx.hir().get_by_hir_id(parent_id); if let rustc::hir::Node::Expr(e) = parent_node { - if let ExprKind::If(_, _, _) = e.node { + if higher::if_block(&e).is_some() { return true; } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 9377ff3e3a0b..743c0c4224a2 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,7 +8,7 @@ use syntax::ptr::P; use crate::utils::paths::*; use crate::utils::sugg::Sugg; -use crate::utils::{match_type, span_lint_and_then, SpanlessEq}; +use crate::utils::{higher, match_type, span_lint_and_then, SpanlessEq}; declare_clippy_lint! { /// **What it does:** Checks for expressions that could be replaced by the question mark operator. @@ -48,7 +48,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 ExprKind::If(if_expr, body, else_) = &expr.node; + if let Some((if_expr, body, else_)) = higher::if_block(&expr); if let ExprKind::MethodCall(segment, _, args) = &if_expr.node; if segment.ident.name == "is_none"; if Self::expression_returns_none(cx, body); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 63d75be1da20..2d85189d111d 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -319,13 +319,6 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: 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::While(ref cond, ref block, _) => { check_expr(cx, cond, bindings); check_block(cx, block, bindings); diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 9f7cdf986489..348579f75d18 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -2,7 +2,7 @@ use if_chain::if_chain; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; +use crate::utils::{higher::if_block, in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use rustc::hir::intravisit::*; use rustc::hir::*; use syntax::source_map::Span; @@ -130,7 +130,7 @@ impl<'a, 'tcx: 'a> UnwrappableVariablesVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr) { - if let ExprKind::If(cond, then, els) = &expr.node { + if let Some((cond, then, els)) = if_block(&expr) { walk_expr(self, cond); self.visit_branch(cond, then, false); if let Some(els) = els { diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index ec8079f18249..5b88494ae7b7 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; +use crate::utils::{get_attr, higher}; use rustc::hir; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::{BindingAnnotation, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; @@ -187,6 +187,32 @@ struct PrintVisitor { 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!("{}.node", self.current); match expr.node { @@ -296,25 +322,6 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = cast_pat; self.visit_expr(expr); }, - 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::While(ref cond, ref body, _) => { let cond_pat = self.next("cond"); let body_pat = self.next("body"); @@ -684,6 +691,10 @@ fn desugaring_name(des: hir::MatchSource) -> String { "MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", contains_else_clause ), + 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/higher.rs b/clippy_lints/src/utils/higher.rs index 6bb45b2c73f8..5c9f5e25f4d8 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -199,6 +199,27 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &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(expr: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr, Option<&hir::Expr>)> { + if let hir::ExprKind::Match(ref cond, ref arms, hir::MatchSource::IfDesugar { contains_else_clause }) = expr.node { + let cond = if let hir::ExprKind::DropTemps(ref cond) = cond.node { + 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]` diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index e1ddc69f25ee..de1299004678 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -114,9 +114,6 @@ impl<'a, 'tcx: 'a> 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()) @@ -493,15 +490,6 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _, _) -> _ = ExprKind::InlineAsm; c.hash(&mut self.s); }, - ExprKind::If(ref cond, ref t, ref e) => { - let c: fn(_, _, _) -> _ = ExprKind::If; - c.hash(&mut self.s); - self.hash_expr(cond); - self.hash_expr(&**t); - if let Some(ref e) = *e { - self.hash_expr(e); - } - }, ExprKind::Lit(ref l) => { let c: fn(_) -> _ = ExprKind::Lit; c.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index cde911940dc1..633ebb3dd423 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -209,15 +209,6 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { print_expr(cx, e, indent + 1); println!("{}target type: {:?}", ind, target); }, - hir::ExprKind::If(ref e, _, ref els) => { - println!("{}If", ind); - println!("{}condition:", ind); - print_expr(cx, e, indent + 1); - if let Some(ref els) = *els { - println!("{}else:", ind); - print_expr(cx, els, indent + 1); - } - }, hir::ExprKind::While(ref cond, _, _) => { println!("{}While", ind); println!("{}condition:", ind); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 56837109877d..7ebaeb0951f7 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -40,6 +40,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::Applicability; use syntax::ast::{self, LitKind}; use syntax::attr; +use syntax::ext::hygiene::ExpnFormat; use syntax::source_map::{Span, DUMMY_SP}; use syntax::symbol::{keywords, Symbol}; @@ -90,7 +91,15 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool { /// Returns `true` if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { - span.ctxt().outer().expn_info().is_some() + if let Some(info) = span.ctxt().outer().expn_info() { + if let ExpnFormat::CompilerDesugaring(..) = info.format { + false + } else { + true + } + } else { + false + } } // If the snippet is empty, it's an attribute that was inserted during macro diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index be6e6069402e..7d029d0f61e2 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -94,7 +94,6 @@ impl<'a> Sugg<'a> { hir::ExprKind::AddrOf(..) | hir::ExprKind::Box(..) | hir::ExprKind::Closure(.., _) - | hir::ExprKind::If(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet), hir::ExprKind::Continue(..) diff --git a/tests/ui/author/if.rs b/tests/ui/author/if.rs new file mode 100644 index 000000000000..2e9cb1466d0b --- /dev/null +++ b/tests/ui/author/if.rs @@ -0,0 +1,10 @@ +#[allow(clippy::all)] + +fn main() { + #[clippy::author] + let _ = if true { + 1 == 1; + } else { + 2 == 2; + }; +} diff --git a/tests/ui/author/if.stderr b/tests/ui/author/if.stderr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/ui/author/if.stdout b/tests/ui/author/if.stdout new file mode 100644 index 000000000000..bff6546a9314 --- /dev/null +++ b/tests/ui/author/if.stdout @@ -0,0 +1,27 @@ +if_chain! { + if let StmtKind::Local(ref local) = stmt.node; + if let Some(ref init) = local.init; + if let Some((ref cond, ref then, Some(else_))) = higher::if_block(&init); + if let ExprKind::Block(ref block) = else_.node; + if let StmtKind::Semi(ref e, _) = block.node + if let ExprKind::Binary(ref op, ref left, ref right) = e.node; + if BinOpKind::Eq == op.node; + if let ExprKind::Lit(ref lit) = left.node; + if let LitKind::Int(2, _) = lit.node; + if let ExprKind::Lit(ref lit1) = right.node; + if let LitKind::Int(2, _) = lit1.node; + if let ExprKind::Lit(ref lit2) = cond.node; + if let LitKind::Bool(true) = lit2.node; + if let ExprKind::Block(ref block1) = then.node; + if let StmtKind::Semi(ref e1, _) = block1.node + if let ExprKind::Binary(ref op1, ref left1, ref right1) = e1.node; + if BinOpKind::Eq == op1.node; + if let ExprKind::Lit(ref lit3) = left1.node; + if let LitKind::Int(1, _) = lit3.node; + if let ExprKind::Lit(ref lit4) = right1.node; + if let LitKind::Int(1, _) = lit4.node; + if let PatKind::Wild = local.pat.node; + then { + // report your lint here + } +} diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index 659fd56f9a9d..f5342be631b0 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -10,7 +10,7 @@ fn main() { for _ in &[1, 2, 3] {} for _ in vec![X, X] {} for _ in &vec![X, X] {} - for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() + for _ in [1, 2, 3].iter() {} //~ ERROR equivalent to .iter() let _ = [1, 2, 3].iter(); //~ ERROR equivalent to .iter() let _ = vec![1, 2, 3].into_iter(); diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index c3e5c85618b8..931e4880f938 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,8 +1,8 @@ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:15:23 + --> $DIR/into_iter_on_ref.rs:13:24 | -LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +LL | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` | note: lint level defined here --> $DIR/into_iter_on_ref.rs:4:9 @@ -10,6 +10,12 @@ note: lint level defined here LL | #![deny(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: this .into_iter() call is equivalent to .iter() and will not move the array + --> $DIR/into_iter_on_ref.rs:15:23 + | +LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + error: this .into_iter() call is equivalent to .iter() and will not move the Vec --> $DIR/into_iter_on_ref.rs:17:30 | @@ -168,5 +174,5 @@ error: this .into_iter() call is equivalent to .iter() and will not move the Pat LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors