Skip to content

Commit b21a91a

Browse files
committed
Replace local variables signifying "done" or "loop break", use ControlFlow rust-lang#12830
1 parent 615284a commit b21a91a

9 files changed

+100
-119
lines changed

clippy_lints/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(array_windows)]
22
#![feature(binary_heap_into_iter_sorted)]
33
#![feature(box_patterns)]
4+
#![feature(control_flow_enum)]
45
#![feature(f128)]
56
#![feature(f16)]
67
#![feature(if_let_guard)]

clippy_lints/src/lifetimes.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_session::declare_lint_pass;
2222
use rustc_span::def_id::LocalDefId;
2323
use rustc_span::symbol::{kw, Ident, Symbol};
2424
use rustc_span::Span;
25+
use std::ops::ControlFlow;
2526

2627
declare_clippy_lint! {
2728
/// ### What it does
@@ -380,11 +381,8 @@ fn could_use_elision<'tcx>(
380381
return None;
381382
}
382383

383-
let mut checker = BodyLifetimeChecker {
384-
lifetimes_used_in_body: false,
385-
};
386-
checker.visit_expr(body.value);
387-
if checker.lifetimes_used_in_body {
384+
let mut checker = BodyLifetimeChecker;
385+
if checker.visit_expr(body.value).is_break() {
388386
return None;
389387
}
390388
}
@@ -694,15 +692,15 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
694692
}
695693
}
696694

697-
struct BodyLifetimeChecker {
698-
lifetimes_used_in_body: bool,
699-
}
695+
struct BodyLifetimeChecker;
700696

701697
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
698+
type Result = ControlFlow<()>;
702699
// for lifetimes as parameters of generics
703-
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
700+
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) -> ControlFlow<()> {
704701
if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
705-
self.lifetimes_used_in_body = true;
702+
return ControlFlow::Break(());
706703
}
704+
ControlFlow::Continue(())
707705
}
708706
}

clippy_lints/src/loops/mut_range_bound.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_lint::LateContext;
88
use rustc_middle::mir::FakeReadCause;
99
use rustc_middle::ty;
1010
use rustc_span::Span;
11+
use std::ops::ControlFlow;
1112

1213
pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
1314
if let Some(higher::Range {
@@ -114,7 +115,6 @@ impl MutatePairDelegate<'_, '_> {
114115
struct BreakAfterExprVisitor {
115116
hir_id: HirId,
116117
past_expr: bool,
117-
past_candidate: bool,
118118
break_after_expr: bool,
119119
}
120120

@@ -123,7 +123,6 @@ impl BreakAfterExprVisitor {
123123
let mut visitor = BreakAfterExprVisitor {
124124
hir_id,
125125
past_expr: false,
126-
past_candidate: false,
127126
break_after_expr: false,
128127
};
129128

@@ -135,21 +134,19 @@ impl BreakAfterExprVisitor {
135134
}
136135

137136
impl<'tcx> Visitor<'tcx> for BreakAfterExprVisitor {
138-
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
139-
if self.past_candidate {
140-
return;
141-
}
142-
137+
type Result = ControlFlow<()>;
138+
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
143139
if expr.hir_id == self.hir_id {
144140
self.past_expr = true;
141+
ControlFlow::Continue(())
145142
} else if self.past_expr {
146143
if matches!(&expr.kind, ExprKind::Break(..)) {
147144
self.break_after_expr = true;
148145
}
149146

150-
self.past_candidate = true;
147+
ControlFlow::Break(())
151148
} else {
152-
intravisit::walk_expr(self, expr);
149+
intravisit::walk_expr(self, expr)
153150
}
154151
}
155152
}

clippy_lints/src/loops/while_immutable_condition.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_hir::def_id::DefIdMap;
77
use rustc_hir::intravisit::{walk_expr, Visitor};
88
use rustc_hir::{Expr, ExprKind, HirIdSet, QPath};
99
use rustc_lint::LateContext;
10+
use std::ops::ControlFlow;
1011

1112
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
1213
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: &'
3536
};
3637
let mutable_static_in_cond = var_visitor.def_ids.items().any(|(_, v)| *v);
3738

38-
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
39-
has_break_or_return: false,
40-
};
41-
has_break_or_return_visitor.visit_expr(expr);
42-
let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
39+
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor;
40+
let has_break_or_return = has_break_or_return_visitor.visit_expr(expr).is_break();
4341

4442
if no_cond_variable_mutated && !mutable_static_in_cond {
4543
span_lint_and_then(
@@ -59,25 +57,19 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
5957
}
6058
}
6159

62-
struct HasBreakOrReturnVisitor {
63-
has_break_or_return: bool,
64-
}
60+
struct HasBreakOrReturnVisitor;
6561

6662
impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
67-
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
68-
if self.has_break_or_return {
69-
return;
70-
}
71-
63+
type Result = ControlFlow<()>;
64+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<()> {
7265
match expr.kind {
7366
ExprKind::Ret(_) | ExprKind::Break(_, _) => {
74-
self.has_break_or_return = true;
75-
return;
67+
return ControlFlow::Break(());
7668
},
7769
_ => {},
7870
}
7971

80-
walk_expr(self, expr);
72+
walk_expr(self, expr)
8173
}
8274
}
8375

clippy_lints/src/methods/option_map_unwrap_or.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath};
1010
use rustc_lint::LateContext;
1111
use rustc_middle::hir::nested_filter;
1212
use rustc_span::{sym, Span};
13+
use std::ops::ControlFlow;
1314

1415
use super::MAP_UNWRAP_OR;
1516

@@ -54,15 +55,14 @@ pub(super) fn check<'tcx>(
5455
let mut reference_visitor = ReferenceVisitor {
5556
cx,
5657
identifiers: unwrap_visitor.identifiers,
57-
found_reference: false,
5858
unwrap_or_span: unwrap_arg.span,
5959
};
6060

6161
let map = cx.tcx.hir();
6262
let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id));
63-
reference_visitor.visit_body(body);
6463

65-
if reference_visitor.found_reference {
64+
// Visit the body, and return if we've found a reference
65+
if reference_visitor.visit_body(body).is_break() {
6666
return;
6767
}
6868
}
@@ -151,29 +151,27 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
151151
struct ReferenceVisitor<'a, 'tcx> {
152152
cx: &'a LateContext<'tcx>,
153153
identifiers: FxHashSet<HirId>,
154-
found_reference: bool,
155154
unwrap_or_span: Span,
156155
}
157156

158157
impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
159158
type NestedFilter = nested_filter::All;
160-
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) {
159+
type Result = ControlFlow<()>;
160+
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> {
161161
// If we haven't found a reference yet, check if this references
162162
// one of the locals that was moved in the `unwrap_or` argument.
163163
// We are only interested in exprs that appear before the `unwrap_or` call.
164-
if !self.found_reference {
165-
if expr.span < self.unwrap_or_span
166-
&& let ExprKind::Path(ref path) = expr.kind
167-
&& let QPath::Resolved(_, path) = path
168-
&& let Res::Local(local_id) = path.res
169-
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
170-
&& let PatKind::Binding(_, local_id, ..) = pat.kind
171-
&& self.identifiers.contains(&local_id)
172-
{
173-
self.found_reference = true;
174-
}
175-
rustc_hir::intravisit::walk_expr(self, expr);
164+
if expr.span < self.unwrap_or_span
165+
&& let ExprKind::Path(ref path) = expr.kind
166+
&& let QPath::Resolved(_, path) = path
167+
&& let Res::Local(local_id) = path.res
168+
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
169+
&& let PatKind::Binding(_, local_id, ..) = pat.kind
170+
&& self.identifiers.contains(&local_id)
171+
{
172+
return ControlFlow::Break(());
176173
}
174+
rustc_hir::intravisit::walk_expr(self, expr)
177175
}
178176

179177
fn nested_visit_map(&mut self) -> Self::Map {

clippy_lints/src/redundant_closure_call.rs

+8-17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro;
1414
use rustc_middle::ty;
1515
use rustc_session::declare_lint_pass;
1616
use rustc_span::ExpnKind;
17+
use std::ops::ControlFlow;
1718

1819
declare_clippy_lint! {
1920
/// ### What it does
@@ -42,24 +43,15 @@ declare_clippy_lint! {
4243
declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]);
4344

4445
// Used to find `return` statements or equivalents e.g., `?`
45-
struct ReturnVisitor {
46-
found_return: bool,
47-
}
48-
49-
impl ReturnVisitor {
50-
#[must_use]
51-
fn new() -> Self {
52-
Self { found_return: false }
53-
}
54-
}
46+
struct ReturnVisitor;
5547

5648
impl<'tcx> Visitor<'tcx> for ReturnVisitor {
57-
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
49+
type Result = ControlFlow<()>;
50+
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> ControlFlow<()> {
5851
if let ExprKind::Ret(_) | ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind {
59-
self.found_return = true;
60-
} else {
61-
hir_visit::walk_expr(self, ex);
52+
return ControlFlow::Break(());
6253
}
54+
hir_visit::walk_expr(self, ex)
6355
}
6456
}
6557

@@ -101,9 +93,8 @@ fn find_innermost_closure<'tcx>(
10193
while let ExprKind::Closure(closure) = expr.kind
10294
&& let body = cx.tcx.hir().body(closure.body)
10395
&& {
104-
let mut visitor = ReturnVisitor::new();
105-
visitor.visit_expr(body.value);
106-
!visitor.found_return
96+
let mut visitor = ReturnVisitor;
97+
!visitor.visit_expr(body.value).is_break()
10798
}
10899
&& steps > 0
109100
{

clippy_lints/src/unconditional_recursion.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_session::impl_lint_pass;
1616
use rustc_span::symbol::{kw, Ident};
1717
use rustc_span::{sym, Span};
1818
use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
19+
use std::ops::ControlFlow;
1920

2021
declare_clippy_lint! {
2122
/// ### What it does
@@ -276,7 +277,6 @@ struct CheckCalls<'a, 'tcx> {
276277
cx: &'a LateContext<'tcx>,
277278
map: Map<'tcx>,
278279
implemented_ty_id: DefId,
279-
found_default_call: bool,
280280
method_span: Span,
281281
}
282282

@@ -285,16 +285,14 @@ where
285285
'tcx: 'a,
286286
{
287287
type NestedFilter = nested_filter::OnlyBodies;
288+
type Result = ControlFlow<()>;
288289

289290
fn nested_visit_map(&mut self) -> Self::Map {
290291
self.map
291292
}
292293

293-
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
294-
if self.found_default_call {
295-
return;
296-
}
297-
walk_expr(self, expr);
294+
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
295+
walk_expr(self, expr)?;
298296

299297
if let ExprKind::Call(f, _) = expr.kind
300298
&& let ExprKind::Path(qpath) = f.kind
@@ -303,9 +301,10 @@ where
303301
&& let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id)
304302
&& self.cx.tcx.is_diagnostic_item(sym::Default, trait_def_id)
305303
{
306-
self.found_default_call = true;
307304
span_error(self.cx, self.method_span, expr);
305+
return ControlFlow::Break(());
308306
}
307+
ControlFlow::Continue(())
309308
}
310309
}
311310

@@ -383,7 +382,6 @@ impl UnconditionalRecursion {
383382
cx,
384383
map: cx.tcx.hir(),
385384
implemented_ty_id,
386-
found_default_call: false,
387385
method_span,
388386
};
389387
walk_body(&mut c, body);

0 commit comments

Comments
 (0)