Skip to content

Commit c7cfe7f

Browse files
committed
Auto merge of #13156 - y21:for_each_expr_visitor_refactor, r=xFrednet
Remove unnecessary `res` field in `for_each_expr` visitors Small refactor in the `for_each_expr*` visitors. This should not change anything functionally. Instead of storing the final value `Option<B>` in the visitor and setting it to `Some` when we get a `ControlFlow::Break(B)` from the closure, we can just directly return it from the visitor itself now that visitors support that. cc #12829 and #12830 (comment) changelog: none
2 parents 37f4fbb + de1e163 commit c7cfe7f

File tree

1 file changed

+48
-50
lines changed

1 file changed

+48
-50
lines changed

clippy_utils/src/visitors.rs

+48-50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::ty::needs_ordered_drop;
22
use crate::{get_enclosing_block, path_to_local_id};
33
use core::ops::ControlFlow;
4+
use rustc_ast::visit::{try_visit, VisitorResult};
45
use rustc_hir as hir;
56
use rustc_hir::def::{CtorKind, DefKind, Res};
67
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
@@ -50,44 +51,46 @@ impl Continue for Descend {
5051
/// A type which can be visited.
5152
pub trait Visitable<'tcx> {
5253
/// Calls the corresponding `visit_*` function on the visitor.
53-
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
54+
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result;
5455
}
5556
impl<'tcx, T> Visitable<'tcx> for &'tcx [T]
5657
where
5758
&'tcx T: Visitable<'tcx>,
5859
{
59-
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
60+
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
6061
for x in self {
61-
x.visit(visitor);
62+
try_visit!(x.visit(visitor));
6263
}
64+
V::Result::output()
6365
}
6466
}
6567
impl<'tcx, A, B> Visitable<'tcx> for (A, B)
6668
where
6769
A: Visitable<'tcx>,
6870
B: Visitable<'tcx>,
6971
{
70-
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
72+
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
7173
let (a, b) = self;
72-
a.visit(visitor);
73-
b.visit(visitor);
74+
try_visit!(a.visit(visitor));
75+
b.visit(visitor)
7476
}
7577
}
7678
impl<'tcx, T> Visitable<'tcx> for Option<T>
7779
where
7880
T: Visitable<'tcx>,
7981
{
80-
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
82+
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
8183
if let Some(x) = self {
82-
x.visit(visitor);
84+
try_visit!(x.visit(visitor));
8385
}
86+
V::Result::output()
8487
}
8588
}
8689
macro_rules! visitable_ref {
8790
($t:ident, $f:ident) => {
8891
impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
89-
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
90-
visitor.$f(self);
92+
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
93+
visitor.$f(self)
9194
}
9295
}
9396
};
@@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
104107
node: impl Visitable<'tcx>,
105108
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
106109
) -> Option<B> {
107-
struct V<B, F> {
110+
struct V<F> {
108111
f: F,
109-
res: Option<B>,
110112
}
111-
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
112-
type Result = ControlFlow<()>;
113+
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<F> {
114+
type Result = ControlFlow<B>;
113115

114-
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> {
115-
if self.res.is_some() {
116-
return ControlFlow::Break(());
117-
}
116+
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
118117
match (self.f)(e) {
119118
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
120-
ControlFlow::Break(b) => {
121-
self.res = Some(b);
122-
ControlFlow::Break(())
123-
},
119+
ControlFlow::Break(b) => ControlFlow::Break(b),
124120
ControlFlow::Continue(_) => ControlFlow::Continue(()),
125121
}
126122
}
127123

128124
// Avoid unnecessary `walk_*` calls.
129-
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> {
125+
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
130126
ControlFlow::Continue(())
131127
}
132-
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> {
128+
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
133129
ControlFlow::Continue(())
134130
}
135-
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> {
131+
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
136132
ControlFlow::Continue(())
137133
}
138134
// Avoid monomorphising all `visit_*` functions.
139-
fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> {
135+
fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
140136
ControlFlow::Continue(())
141137
}
142138
}
143-
let mut v = V { f, res: None };
144-
node.visit(&mut v);
145-
v.res
139+
let mut v = V { f };
140+
node.visit(&mut v).break_value()
146141
}
147142

148143
/// Calls the given function once for each expression contained. This will enter bodies, but not
@@ -152,44 +147,47 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
152147
node: impl Visitable<'tcx>,
153148
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
154149
) -> Option<B> {
155-
struct V<'tcx, B, F> {
150+
struct V<'tcx, F> {
156151
tcx: TyCtxt<'tcx>,
157152
f: F,
158-
res: Option<B>,
159153
}
160-
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, B, F> {
154+
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, F> {
161155
type NestedFilter = nested_filter::OnlyBodies;
156+
type Result = ControlFlow<B>;
157+
162158
fn nested_visit_map(&mut self) -> Self::Map {
163159
self.tcx.hir()
164160
}
165161

166-
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
167-
if self.res.is_some() {
168-
return;
169-
}
162+
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
170163
match (self.f)(e) {
171164
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
172-
ControlFlow::Break(b) => self.res = Some(b),
173-
ControlFlow::Continue(_) => (),
165+
ControlFlow::Break(b) => ControlFlow::Break(b),
166+
ControlFlow::Continue(_) => ControlFlow::Continue(()),
174167
}
175168
}
176169

177170
// Only walk closures
178-
fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
171+
fn visit_anon_const(&mut self, _: &'tcx AnonConst) -> Self::Result {
172+
ControlFlow::Continue(())
173+
}
179174
// Avoid unnecessary `walk_*` calls.
180-
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
181-
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
182-
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
175+
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
176+
ControlFlow::Continue(())
177+
}
178+
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
179+
ControlFlow::Continue(())
180+
}
181+
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
182+
ControlFlow::Continue(())
183+
}
183184
// Avoid monomorphising all `visit_*` functions.
184-
fn visit_nested_item(&mut self, _: ItemId) {}
185+
fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
186+
ControlFlow::Continue(())
187+
}
185188
}
186-
let mut v = V {
187-
tcx: cx.tcx,
188-
f,
189-
res: None,
190-
};
191-
node.visit(&mut v);
192-
v.res
189+
let mut v = V { tcx: cx.tcx, f };
190+
node.visit(&mut v).break_value()
193191
}
194192

195193
/// returns `true` if expr contains match expr desugared from try

0 commit comments

Comments
 (0)