diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index a55836a972fb..f5dae79d37ce 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -7,6 +7,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -44,8 +45,8 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]); impl<'tcx> LateLintPass<'tcx> for IfLetMutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - let mut arm_visit = ArmVisitor { found_mutex: None, cx }; - let mut op_visit = OppVisitor { found_mutex: None, cx }; + let mut arm_visit = ArmVisitor { cx }; + let mut op_visit = OppVisitor { cx }; if let Some(higher::IfLet { let_expr, if_then, @@ -53,12 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { .. }) = higher::IfLet::hir(cx, expr) { - op_visit.visit_expr(let_expr); - if let Some(op_mutex) = op_visit.found_mutex { - arm_visit.visit_expr(if_then); - arm_visit.visit_expr(if_else); + let found_op_mutex = op_visit.visit_expr(let_expr).break_value(); + if let Some(op_mutex) = found_op_mutex { + let mut found_mutex = arm_visit.visit_expr(if_then).break_value(); + if found_mutex.is_none() { + found_mutex = arm_visit.visit_expr(if_else).break_value(); + }; - if let Some(arm_mutex) = arm_visit.found_mutex_if_same_as(op_mutex) { + if let Some(arm_mutex) = arm_visit.found_mutex_if_same_as(op_mutex, found_mutex) { let diag = |diag: &mut Diag<'_, ()>| { diag.span_label( op_mutex.span, @@ -85,39 +88,37 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { /// Checks if `Mutex::lock` is called in the `if let` expr. pub struct OppVisitor<'a, 'tcx> { - found_mutex: Option<&'tcx Expr<'tcx>>, cx: &'a LateContext<'tcx>, } impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + type Result = ControlFlow<&'tcx Expr<'tcx>>; + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<&'tcx Expr<'tcx>> { if let Some(mutex) = is_mutex_lock_call(self.cx, expr) { - self.found_mutex = Some(mutex); - return; + return ControlFlow::Break(mutex); } - visit::walk_expr(self, expr); + visit::walk_expr(self, expr) } } /// Checks if `Mutex::lock` is called in any of the branches. pub struct ArmVisitor<'a, 'tcx> { - found_mutex: Option<&'tcx Expr<'tcx>>, cx: &'a LateContext<'tcx>, } impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + type Result = ControlFlow<&'tcx Expr<'tcx>>; + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<&'tcx Expr<'tcx>> { if let Some(mutex) = is_mutex_lock_call(self.cx, expr) { - self.found_mutex = Some(mutex); - return; + return ControlFlow::Break(mutex); } - visit::walk_expr(self, expr); + visit::walk_expr(self, expr) } } impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { - fn found_mutex_if_same_as(&self, op_mutex: &Expr<'_>) -> Option<&Expr<'_>> { - self.found_mutex.and_then(|arm_mutex| { + fn found_mutex_if_same_as(&self, op_mutex: &Expr<'_>, found_mutex: Option<&'tcx Expr<'tcx>>) -> Option<&Expr<'_>> { + found_mutex.and_then(|arm_mutex| { SpanlessEq::new(self.cx) .eq_expr(op_mutex, arm_mutex) .then_some(arm_mutex) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 25cd76104007..15e692bcc0de 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,6 +1,7 @@ #![feature(array_windows)] #![feature(binary_heap_into_iter_sorted)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 443d6189c1f7..9f063ced313d 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -22,6 +22,7 @@ use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -380,11 +381,8 @@ fn could_use_elision<'tcx>( return None; } - let mut checker = BodyLifetimeChecker { - lifetimes_used_in_body: false, - }; - checker.visit_expr(body.value); - if checker.lifetimes_used_in_body { + let mut checker = BodyLifetimeChecker; + if checker.visit_expr(body.value).is_break() { return None; } } @@ -694,15 +692,15 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' } } -struct BodyLifetimeChecker { - lifetimes_used_in_body: bool, -} +struct BodyLifetimeChecker; impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { + type Result = ControlFlow<()>; // for lifetimes as parameters of generics - fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { + fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) -> ControlFlow<()> { if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime { - self.lifetimes_used_in_body = true; + return ControlFlow::Break(()); } + ControlFlow::Continue(()) } } diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 6c6a9a1a2e00..cf607bb881d6 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -8,6 +8,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty; use rustc_span::Span; +use std::ops::ControlFlow; pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { if let Some(higher::Range { @@ -114,7 +115,6 @@ impl MutatePairDelegate<'_, '_> { struct BreakAfterExprVisitor { hir_id: HirId, past_expr: bool, - past_candidate: bool, break_after_expr: bool, } @@ -123,7 +123,6 @@ impl BreakAfterExprVisitor { let mut visitor = BreakAfterExprVisitor { hir_id, past_expr: false, - past_candidate: false, break_after_expr: false, }; @@ -135,21 +134,19 @@ impl BreakAfterExprVisitor { } impl<'tcx> Visitor<'tcx> for BreakAfterExprVisitor { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if self.past_candidate { - return; - } - + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> { if expr.hir_id == self.hir_id { self.past_expr = true; + ControlFlow::Continue(()) } else if self.past_expr { if matches!(&expr.kind, ExprKind::Break(..)) { self.break_after_expr = true; } - self.past_candidate = true; + return ControlFlow::Break(()); } else { - intravisit::walk_expr(self, expr); + intravisit::walk_expr(self, expr) } } } diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs index 3dff826cb85c..e7b3a2c4973c 100644 --- a/clippy_lints/src/loops/while_immutable_condition.rs +++ b/clippy_lints/src/loops/while_immutable_condition.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefIdMap; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Expr, ExprKind, HirIdSet, QPath}; use rustc_lint::LateContext; +use std::ops::ControlFlow; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { if constant(cx, cx.typeck_results(), cond).is_some() { @@ -35,11 +36,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &' }; let mutable_static_in_cond = var_visitor.def_ids.items().any(|(_, v)| *v); - let mut has_break_or_return_visitor = HasBreakOrReturnVisitor { - has_break_or_return: false, - }; - has_break_or_return_visitor.visit_expr(expr); - let has_break_or_return = has_break_or_return_visitor.has_break_or_return; + let mut has_break_or_return_visitor = HasBreakOrReturnVisitor; + let has_break_or_return = has_break_or_return_visitor.visit_expr(expr).is_break(); if no_cond_variable_mutated && !mutable_static_in_cond { span_lint_and_then( @@ -59,25 +57,19 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &' } } -struct HasBreakOrReturnVisitor { - has_break_or_return: bool, -} +struct HasBreakOrReturnVisitor; impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.has_break_or_return { - return; - } - + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<()> { match expr.kind { ExprKind::Ret(_) | ExprKind::Break(_, _) => { - self.has_break_or_return = true; - return; + return ControlFlow::Break(()); }, _ => {}, } - walk_expr(self, expr); + walk_expr(self, expr) } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 3d326bc99f95..2afaccee23e3 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -10,6 +10,7 @@ use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_span::{sym, Span}; +use std::ops::ControlFlow; use super::MAP_UNWRAP_OR; @@ -54,17 +55,16 @@ pub(super) fn check<'tcx>( let mut reference_visitor = ReferenceVisitor { cx, identifiers: unwrap_visitor.identifiers, - found_reference: false, unwrap_or_span: unwrap_arg.span, }; let map = cx.tcx.hir(); let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id)); - reference_visitor.visit_body(body); - if reference_visitor.found_reference { + // Visit the body, and return if we've found a reference + if reference_visitor.visit_body(body).is_break() { return; - } + }; } if !unwrap_arg.span.eq_ctxt(map_span) { @@ -151,29 +151,27 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { struct ReferenceVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, identifiers: FxHashSet, - found_reference: bool, unwrap_or_span: Span, } impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> { type NestedFilter = nested_filter::All; - fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> { // If we haven't found a reference yet, check if this references // one of the locals that was moved in the `unwrap_or` argument. // We are only interested in exprs that appear before the `unwrap_or` call. - if !self.found_reference { - if expr.span < self.unwrap_or_span - && let ExprKind::Path(ref path) = expr.kind - && let QPath::Resolved(_, path) = path - && let Res::Local(local_id) = path.res - && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) - && let PatKind::Binding(_, local_id, ..) = pat.kind - && self.identifiers.contains(&local_id) - { - self.found_reference = true; - } - rustc_hir::intravisit::walk_expr(self, expr); + if expr.span < self.unwrap_or_span + && let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + return ControlFlow::Break(()); } + rustc_hir::intravisit::walk_expr(self, expr) } fn nested_visit_map(&mut self) -> Self::Map { diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 47d3ed08b8ec..bad9b979203f 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::ExpnKind; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -42,24 +43,15 @@ declare_clippy_lint! { declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]); // Used to find `return` statements or equivalents e.g., `?` -struct ReturnVisitor { - found_return: bool, -} - -impl ReturnVisitor { - #[must_use] - fn new() -> Self { - Self { found_return: false } - } -} +struct ReturnVisitor; impl<'tcx> Visitor<'tcx> for ReturnVisitor { - fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> ControlFlow<()> { if let ExprKind::Ret(_) | ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind { - self.found_return = true; - } else { - hir_visit::walk_expr(self, ex); + return ControlFlow::Break(()); } + hir_visit::walk_expr(self, ex) } } @@ -101,9 +93,8 @@ fn find_innermost_closure<'tcx>( while let ExprKind::Closure(closure) = expr.kind && let body = cx.tcx.hir().body(closure.body) && { - let mut visitor = ReturnVisitor::new(); - visitor.visit_expr(body.value); - !visitor.found_return + let mut visitor = ReturnVisitor; + !visitor.visit_expr(body.value).is_break() } && steps > 0 { diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index 6ba98a92423c..42100e1d755c 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -16,6 +16,7 @@ use rustc_session::impl_lint_pass; use rustc_span::symbol::{kw, Ident}; use rustc_span::{sym, Span}; use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -276,7 +277,6 @@ struct CheckCalls<'a, 'tcx> { cx: &'a LateContext<'tcx>, map: Map<'tcx>, implemented_ty_id: DefId, - found_default_call: bool, method_span: Span, } @@ -285,16 +285,14 @@ where 'tcx: 'a, { type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow<()>; fn nested_visit_map(&mut self) -> Self::Map { self.map } - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if self.found_default_call { - return; - } - walk_expr(self, expr); + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> { + walk_expr(self, expr)?; if let ExprKind::Call(f, _) = expr.kind && let ExprKind::Path(qpath) = f.kind @@ -303,9 +301,10 @@ where && let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id) && self.cx.tcx.is_diagnostic_item(sym::Default, trait_def_id) { - self.found_default_call = true; span_error(self.cx, self.method_span, expr); + return ControlFlow::Break(()); } + ControlFlow::Continue(()) } } @@ -383,7 +382,6 @@ impl UnconditionalRecursion { cx, map: cx.tcx.hir(), implemented_ty_id, - found_default_call: false, method_span, }; walk_body(&mut c, body); diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs index e6f799335d7d..86a811e17ca9 100644 --- a/clippy_lints/src/unused_peekable.rs +++ b/clippy_lints/src/unused_peekable.rs @@ -8,6 +8,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_session::declare_lint_pass; use rustc_span::sym; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -70,15 +71,16 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { return; } - for stmt in &block.stmts[idx..] { - vis.visit_stmt(stmt); - } + let mut found_peek_call = block.stmts[idx..].iter().any(|stmt| vis.visit_stmt(stmt).is_break()); - if let Some(expr) = block.expr { - vis.visit_expr(expr); + if !found_peek_call + && let Some(expr) = block.expr + && vis.visit_expr(expr).is_break() + { + found_peek_call = true; } - if !vis.found_peek_call { + if !found_peek_call { span_lint_hir_and_then( cx, UNUSED_PEEKABLE, @@ -98,31 +100,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { struct PeekableVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, expected_hir_id: HirId, - found_peek_call: bool, } impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> { fn new(cx: &'a LateContext<'tcx>, expected_hir_id: HirId) -> Self { - Self { - cx, - expected_hir_id, - found_peek_call: false, - } + Self { cx, expected_hir_id } } } impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { type NestedFilter = OnlyBodies; + type Result = ControlFlow<()>; fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } - fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if self.found_peek_call { - return; - } - + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> ControlFlow<()> { if path_to_local_id(ex, self.expected_hir_id) { for (_, node) in self.cx.tcx.hir().parent_iter(ex.hir_id) { match node { @@ -137,14 +131,14 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { && func_did == into_iter_did { // Probably a for loop desugar, stop searching - return; + return ControlFlow::Continue(()); } if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) { - self.found_peek_call = true; + return ControlFlow::Break(()); } - return; + return ControlFlow::Continue(()); }, // Catch anything taking a Peekable mutably ExprKind::MethodCall( @@ -162,16 +156,14 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { if matches!(method_name, "peek" | "peek_mut" | "next_if" | "next_if_eq") && arg_is_mut_peekable(self.cx, self_arg) { - self.found_peek_call = true; - return; + return ControlFlow::Break(()); } // foo.some_method() excluding Iterator methods if remaining_args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) && !is_trait_method(self.cx, expr, sym::Iterator) { - self.found_peek_call = true; - return; + return ControlFlow::Break(()); } // foo.by_ref(), keep checking for `peek` @@ -179,41 +171,42 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { continue; } - return; + return ControlFlow::Continue(()); }, ExprKind::AddrOf(_, Mutability::Mut, _) | ExprKind::Unary(..) | ExprKind::DropTemps(_) => { }, - ExprKind::AddrOf(_, Mutability::Not, _) => return, + ExprKind::AddrOf(_, Mutability::Not, _) => return ControlFlow::Continue(()), _ => { - self.found_peek_call = true; - return; + return ControlFlow::Break(()); }, } }, Node::LetStmt(LetStmt { init: Some(init), .. }) => { if arg_is_mut_peekable(self.cx, init) { - self.found_peek_call = true; + return ControlFlow::Break(()); } - return; + return ControlFlow::Continue(()); }, Node::Stmt(stmt) => { match stmt.kind { - StmtKind::Let(_) | StmtKind::Item(_) => self.found_peek_call = true, + StmtKind::Let(_) | StmtKind::Item(_) => { + return ControlFlow::Break(()); + }, StmtKind::Expr(_) | StmtKind::Semi(_) => {}, } - return; + return ControlFlow::Continue(()); }, Node::Block(_) | Node::ExprField(_) => {}, _ => { - return; + return ControlFlow::Continue(()); }, } } } - walk_expr(self, ex); + walk_expr(self, ex) } } diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 3a39e178515d..0847eb1190f0 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -109,30 +109,43 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>( res: Option, } impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow> Visitor<'tcx> for V { - fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { + type Result = ControlFlow<()>; + + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> { if self.res.is_some() { - return; + return ControlFlow::Break(()); } match (self.f)(e) { ControlFlow::Continue(c) if c.descend() => walk_expr(self, e), - ControlFlow::Break(b) => self.res = Some(b), - ControlFlow::Continue(_) => (), + ControlFlow::Break(b) => { + self.res = Some(b); + ControlFlow::Break(()) + }, + ControlFlow::Continue(_) => ControlFlow::Continue(()), } } // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {} - fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {} - fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {} + fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> { + ControlFlow::Continue(()) + } + fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> { + ControlFlow::Continue(()) + } + fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> { + ControlFlow::Continue(()) + } // Avoid monomorphising all `visit_*` functions. - fn visit_nested_item(&mut self, _: ItemId) {} + fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> { + ControlFlow::Continue(()) + } } let mut v = V { f, res: None }; node.visit(&mut v); v.res } -/// Calls the given function once for each expression contained. This will enter bodies, but not +/// Calls the given function once for each expression contained. This will enter bodies, bzut not /// nested items. pub fn for_each_expr<'tcx, B, C: Continue>( cx: &LateContext<'tcx>,