diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 5fb1a988d148..5cad0c859fe2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -671,6 +671,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: HirId) -> NeverLoopResult { match expr.node { ExprKind::Box(ref e) | ExprKind::Unary(_, ref e) + | ExprKind::Use(ref e) | ExprKind::Cast(ref e, _) | ExprKind::Type(ref e, _) | ExprKind::Field(ref e, _) @@ -1461,8 +1462,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( let map = &cx.tcx.hir(); let expr_node_id = expr.hir_id; let parent_scope = map - .get_enclosing_scope(expr_node_id) - .and_then(|id| map.get_enclosing_scope(id)); + .get_enclosing_scope(expr_node_id); if let Some(parent_id) = parent_scope { if let Node::Block(block) = map.get_by_hir_id(parent_id) { for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) { diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 4ddae1d01c13..39bafd84669b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -492,6 +492,12 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, + ExprKind::Use(ref inner) => { + let inner_pat = self.next("inner"); + println!("Use(ref {}) = {};", inner_pat, current); + self.current = inner_pat; + self.visit_expr(inner); + } ExprKind::Err => { println!("Err = {}", current); }, diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 6bb45b2c73f8..b4ca021093a3 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -184,6 +184,7 @@ pub fn is_from_for_desugar(local: &hir::Local) -> bool { /// `for pat in arg { body }` becomes `(pat, arg, body)`. pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { if_chain! { + if let hir::ExprKind::Use(ref expr) = expr.node; if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node; if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.node; if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index e084ed8224c6..9939d712ea49 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -101,6 +101,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprKind::Box(ref l), &ExprKind::Box(ref r)) => self.eq_expr(l, r), + (&ExprKind::Use(ref l), &ExprKind::Use(ref r)) => self.eq_expr(l, r), (&ExprKind::Call(ref l_fun, ref l_args), &ExprKind::Call(ref r_fun, ref r_args)) => { !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, @@ -454,6 +455,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { c.hash(&mut self.s); self.hash_expr(e); }, + ExprKind::Use(ref e) => { + let c: fn(_) -> _ = ExprKind::Use; + c.hash(&mut self.s); + self.hash_expr(e); + }, ExprKind::Call(ref fun, ref args) => { let c: fn(_, _) -> _ = ExprKind::Call; c.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 72c0b5ce365c..566a5edd783d 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -154,6 +154,10 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { println!("{}Box", ind); print_expr(cx, e, indent + 1); }, + hir::ExprKind::Use(ref e) => { + println!("{}Use", ind); + print_expr(cx, e, indent + 1); + }, hir::ExprKind::Array(ref v) => { println!("{}Array", ind); for e in v { diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 72740cee5006..f12c5c3724b4 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -93,6 +93,7 @@ impl<'a> Sugg<'a> { match expr.node { hir::ExprKind::AddrOf(..) | hir::ExprKind::Box(..) + | hir::ExprKind::Use(..) | hir::ExprKind::Closure(.., _) | hir::ExprKind::If(..) | hir::ExprKind::Unary(..) diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index e223ba1a8302..80df9f4e3ee1 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -1,8 +1,6 @@ if_chain! { - if let ExprKind::Block(ref block) = expr.node; - if let StmtKind::Local(ref local) = block.node; - if let Some(ref init) = local.init; - if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node; + if let ExprKind::Use(ref inner) = expr.node; + if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = inner.node; if let ExprKind::Call(ref func, ref args) = expr.node; if let ExprKind::Path(ref path) = func.node; if match_qpath(path, &["{{root}}", "std", "iter", "IntoIterator", "into_iter"]); @@ -13,17 +11,17 @@ if_chain! { // unimplemented: field checks if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; - if let StmtKind::Local(ref local1) = body.node; - if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node; + if let StmtKind::Local(ref local) = body.node; + if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local.pat.node; if name.node.as_str() == "__next"; - if let StmtKind::Expr(ref e, _) = local1.pat.node + if let StmtKind::Expr(ref e, _) = local.pat.node if let ExprKind::Match(ref expr1, ref arms1, MatchSource::ForLoopDesugar) = e.node; if let ExprKind::Call(ref func1, ref args1) = expr1.node; if let ExprKind::Path(ref path2) = func1.node; if match_qpath(path2, &["{{root}}", "std", "iter", "Iterator", "next"]); if args1.len() == 1; - if let ExprKind::AddrOf(MutMutable, ref inner) = args1[0].node; - if let ExprKind::Path(ref path3) = inner.node; + if let ExprKind::AddrOf(MutMutable, ref inner1) = args1[0].node; + if let ExprKind::Path(ref path3) = inner1.node; if match_qpath(path3, &["iter"]); if arms1.len() == 2; if let ExprKind::Assign(ref target, ref value) = arms1[0].body.node; @@ -40,27 +38,23 @@ if_chain! { if arms1[1].pats.len() == 1; if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); - if let StmtKind::Local(ref local2) = path7.node; - if let Some(ref init1) = local2.init; - if let ExprKind::Path(ref path8) = init1.node; + if let StmtKind::Local(ref local1) = path7.node; + if let Some(ref init) = local1.init; + if let ExprKind::Path(ref path8) = init.node; if match_qpath(path8, &["__next"]); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local2.pat.node; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.node; if name1.node.as_str() == "y"; - if let StmtKind::Expr(ref e1, _) = local2.pat.node - if let ExprKind::Block(ref block1) = e1.node; - if let StmtKind::Local(ref local3) = block1.node; - if let Some(ref init2) = local3.init; - if let ExprKind::Path(ref path9) = init2.node; + if let StmtKind::Expr(ref e1, _) = local1.pat.node + if let ExprKind::Block(ref block) = e1.node; + if let StmtKind::Local(ref local2) = block.node; + if let Some(ref init1) = local2.init; + if let ExprKind::Path(ref path9) = init1.node; if match_qpath(path9, &["y"]); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local3.pat.node; + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local2.pat.node; if name2.node.as_str() == "z"; if arms[0].pats.len() == 1; if let PatKind::Binding(BindingAnnotation::Mutable, _, name3, None) = arms[0].pats[0].node; if name3.node.as_str() == "iter"; - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name4, None) = local.pat.node; - if name4.node.as_str() == "_result"; - if let ExprKind::Path(ref path10) = local.pat.node; - if match_qpath(path10, &["_result"]); then { // report your lint here }