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 https://github.com/rust-lang/rust-clippy/pull/12830#discussion_r1627882827 changelog: none
This commit is contained in:
commit
c7cfe7f5e2
@ -1,6 +1,7 @@
|
|||||||
use crate::ty::needs_ordered_drop;
|
use crate::ty::needs_ordered_drop;
|
||||||
use crate::{get_enclosing_block, path_to_local_id};
|
use crate::{get_enclosing_block, path_to_local_id};
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
|
use rustc_ast::visit::{try_visit, VisitorResult};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
|
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
|
||||||
@ -50,16 +51,17 @@ fn descend(&self) -> bool {
|
|||||||
/// A type which can be visited.
|
/// A type which can be visited.
|
||||||
pub trait Visitable<'tcx> {
|
pub trait Visitable<'tcx> {
|
||||||
/// Calls the corresponding `visit_*` function on the visitor.
|
/// Calls the corresponding `visit_*` function on the visitor.
|
||||||
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
|
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result;
|
||||||
}
|
}
|
||||||
impl<'tcx, T> Visitable<'tcx> for &'tcx [T]
|
impl<'tcx, T> Visitable<'tcx> for &'tcx [T]
|
||||||
where
|
where
|
||||||
&'tcx T: Visitable<'tcx>,
|
&'tcx T: Visitable<'tcx>,
|
||||||
{
|
{
|
||||||
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
|
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
|
||||||
for x in self {
|
for x in self {
|
||||||
x.visit(visitor);
|
try_visit!(x.visit(visitor));
|
||||||
}
|
}
|
||||||
|
V::Result::output()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'tcx, A, B> Visitable<'tcx> for (A, B)
|
impl<'tcx, A, B> Visitable<'tcx> for (A, B)
|
||||||
@ -67,27 +69,28 @@ impl<'tcx, A, B> Visitable<'tcx> for (A, B)
|
|||||||
A: Visitable<'tcx>,
|
A: Visitable<'tcx>,
|
||||||
B: Visitable<'tcx>,
|
B: Visitable<'tcx>,
|
||||||
{
|
{
|
||||||
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
|
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
|
||||||
let (a, b) = self;
|
let (a, b) = self;
|
||||||
a.visit(visitor);
|
try_visit!(a.visit(visitor));
|
||||||
b.visit(visitor);
|
b.visit(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'tcx, T> Visitable<'tcx> for Option<T>
|
impl<'tcx, T> Visitable<'tcx> for Option<T>
|
||||||
where
|
where
|
||||||
T: Visitable<'tcx>,
|
T: Visitable<'tcx>,
|
||||||
{
|
{
|
||||||
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
|
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
|
||||||
if let Some(x) = self {
|
if let Some(x) = self {
|
||||||
x.visit(visitor);
|
try_visit!(x.visit(visitor));
|
||||||
}
|
}
|
||||||
|
V::Result::output()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
macro_rules! visitable_ref {
|
macro_rules! visitable_ref {
|
||||||
($t:ident, $f:ident) => {
|
($t:ident, $f:ident) => {
|
||||||
impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
|
impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
|
||||||
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
|
fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
|
||||||
visitor.$f(self);
|
visitor.$f(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
|
|||||||
node: impl Visitable<'tcx>,
|
node: impl Visitable<'tcx>,
|
||||||
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
|
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
|
||||||
) -> Option<B> {
|
) -> Option<B> {
|
||||||
struct V<B, F> {
|
struct V<F> {
|
||||||
f: F,
|
f: F,
|
||||||
res: Option<B>,
|
|
||||||
}
|
}
|
||||||
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
|
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<F> {
|
||||||
type Result = ControlFlow<()>;
|
type Result = ControlFlow<B>;
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> {
|
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
|
||||||
if self.res.is_some() {
|
|
||||||
return ControlFlow::Break(());
|
|
||||||
}
|
|
||||||
match (self.f)(e) {
|
match (self.f)(e) {
|
||||||
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
|
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
|
||||||
ControlFlow::Break(b) => {
|
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||||
self.res = Some(b);
|
|
||||||
ControlFlow::Break(())
|
|
||||||
},
|
|
||||||
ControlFlow::Continue(_) => ControlFlow::Continue(()),
|
ControlFlow::Continue(_) => ControlFlow::Continue(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid unnecessary `walk_*` calls.
|
// Avoid unnecessary `walk_*` calls.
|
||||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> {
|
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> {
|
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> {
|
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
// Avoid monomorphising all `visit_*` functions.
|
// Avoid monomorphising all `visit_*` functions.
|
||||||
fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> {
|
fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut v = V { f, res: None };
|
let mut v = V { f };
|
||||||
node.visit(&mut v);
|
node.visit(&mut v).break_value()
|
||||||
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, but not
|
||||||
@ -152,44 +147,47 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
|
|||||||
node: impl Visitable<'tcx>,
|
node: impl Visitable<'tcx>,
|
||||||
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
|
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
|
||||||
) -> Option<B> {
|
) -> Option<B> {
|
||||||
struct V<'tcx, B, F> {
|
struct V<'tcx, F> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
f: F,
|
f: F,
|
||||||
res: Option<B>,
|
|
||||||
}
|
}
|
||||||
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, B, F> {
|
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, F> {
|
||||||
type NestedFilter = nested_filter::OnlyBodies;
|
type NestedFilter = nested_filter::OnlyBodies;
|
||||||
|
type Result = ControlFlow<B>;
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> Self::Map {
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
self.tcx.hir()
|
self.tcx.hir()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
|
||||||
if self.res.is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
match (self.f)(e) {
|
match (self.f)(e) {
|
||||||
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
|
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
|
||||||
ControlFlow::Break(b) => self.res = Some(b),
|
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||||
ControlFlow::Continue(_) => (),
|
ControlFlow::Continue(_) => ControlFlow::Continue(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only walk closures
|
// Only walk closures
|
||||||
fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
|
fn visit_anon_const(&mut self, _: &'tcx AnonConst) -> Self::Result {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
// Avoid unnecessary `walk_*` calls.
|
// Avoid unnecessary `walk_*` calls.
|
||||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
|
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||||
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
|
ControlFlow::Continue(())
|
||||||
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
|
}
|
||||||
|
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
// Avoid monomorphising all `visit_*` functions.
|
// Avoid monomorphising all `visit_*` functions.
|
||||||
fn visit_nested_item(&mut self, _: ItemId) {}
|
fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let mut v = V {
|
let mut v = V { tcx: cx.tcx, f };
|
||||||
tcx: cx.tcx,
|
node.visit(&mut v).break_value()
|
||||||
f,
|
|
||||||
res: None,
|
|
||||||
};
|
|
||||||
node.visit(&mut v);
|
|
||||||
v.res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns `true` if expr contains match expr desugared from try
|
/// returns `true` if expr contains match expr desugared from try
|
||||||
|
Loading…
Reference in New Issue
Block a user