This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 27bdf3c8c9 simplify TreeNode recursions (#9965)
27bdf3c8c9 is described below

commit 27bdf3c8c976874aae2417cb2aa435448832ecc0
Author: Peter Toth <[email protected]>
AuthorDate: Fri Apr 5 20:19:22 2024 +0200

    simplify TreeNode recursions (#9965)
---
 datafusion/common/src/tree_node.rs            | 288 ++++++++++++++------------
 datafusion/expr/src/tree_node/expr.rs         |  24 +--
 datafusion/expr/src/tree_node/plan.rs         |  48 ++---
 datafusion/optimizer/src/analyzer/subquery.rs |  10 +-
 4 files changed, 184 insertions(+), 186 deletions(-)

diff --git a/datafusion/common/src/tree_node.rs 
b/datafusion/common/src/tree_node.rs
index 554722f37b..8e088e7a0b 100644
--- a/datafusion/common/src/tree_node.rs
+++ b/datafusion/common/src/tree_node.rs
@@ -22,68 +22,25 @@ use std::sync::Arc;
 
 use crate::Result;
 
-/// This macro is used to control continuation behaviors during tree traversals
-/// based on the specified direction. Depending on `$DIRECTION` and the value 
of
-/// the given expression (`$EXPR`), which should be a variant of 
[`TreeNodeRecursion`],
-/// the macro results in the following behavior:
-///
-/// - If the expression returns [`TreeNodeRecursion::Continue`], normal 
execution
-///   continues.
-/// - If it returns [`TreeNodeRecursion::Stop`], recursion halts and propagates
-///   [`TreeNodeRecursion::Stop`].
-/// - If it returns [`TreeNodeRecursion::Jump`], the continuation behavior 
depends
-///   on the traversal direction:
-///   - For `UP` direction, the function returns with 
[`TreeNodeRecursion::Jump`],
-///     bypassing further bottom-up closures until the next top-down closure.
-///   - For `DOWN` direction, the function returns with 
[`TreeNodeRecursion::Continue`],
-///     skipping further exploration.
-///   - If no direction is specified, `Jump` is treated like `Continue`.
-#[macro_export]
-macro_rules! handle_visit_recursion {
-    // Internal helper macro for handling the `Jump` case based on the 
direction:
-    (@handle_jump UP) => {
-        return Ok(TreeNodeRecursion::Jump)
-    };
-    (@handle_jump DOWN) => {
-        return Ok(TreeNodeRecursion::Continue)
-    };
-    (@handle_jump) => {
-        {} // Treat `Jump` like `Continue`, do nothing and continue execution.
-    };
+/// These macros are used to determine continuation during transforming 
traversals.
+macro_rules! handle_transform_recursion {
+    ($F_DOWN:expr, $F_CHILD:expr, $F_UP:expr) => {{
+        #[allow(clippy::redundant_closure_call)]
+        $F_DOWN?
+            .transform_children(|n| n.map_children($F_CHILD))?
+            .transform_parent(|n| $F_UP(n))
+    }};
+}
 
-    // Main macro logic with variables to handle directionality.
-    ($EXPR:expr $(, $DIRECTION:ident)?) => {
-        match $EXPR {
-            TreeNodeRecursion::Continue => {}
-            TreeNodeRecursion::Jump => handle_visit_recursion!(@handle_jump 
$($DIRECTION)?),
-            TreeNodeRecursion::Stop => return Ok(TreeNodeRecursion::Stop),
-        }
-    };
+macro_rules! handle_transform_recursion_down {
+    ($F_DOWN:expr, $F_CHILD:expr) => {{
+        $F_DOWN?.transform_children(|n| n.map_children($F_CHILD))
+    }};
 }
 
-/// This macro is used to determine continuation during combined transforming
-/// traversals.
-///
-/// Depending on the [`TreeNodeRecursion`] the bottom-up closure returns,
-/// [`Transformed::try_transform_node_with()`] decides recursion continuation
-/// and if state propagation is necessary. Then, the same procedure recursively
-/// applies to the children of the node in question.
-macro_rules! handle_transform_recursion {
-    ($F_DOWN:expr, $F_SELF:expr, $F_UP:expr) => {{
-        let pre_visited = $F_DOWN?;
-        match pre_visited.tnr {
-            TreeNodeRecursion::Continue => pre_visited
-                .data
-                .map_children($F_SELF)?
-                .try_transform_node_with($F_UP, TreeNodeRecursion::Jump),
-            #[allow(clippy::redundant_closure_call)]
-            TreeNodeRecursion::Jump => $F_UP(pre_visited.data),
-            TreeNodeRecursion::Stop => return Ok(pre_visited),
-        }
-        .map(|mut post_visited| {
-            post_visited.transformed |= pre_visited.transformed;
-            post_visited
-        })
+macro_rules! handle_transform_recursion_up {
+    ($SELF:expr, $F_CHILD:expr, $F_UP:expr) => {{
+        $SELF.map_children($F_CHILD)?.transform_parent(|n| $F_UP(n))
     }};
 }
 
@@ -128,17 +85,10 @@ pub trait TreeNode: Sized {
         &self,
         visitor: &mut V,
     ) -> Result<TreeNodeRecursion> {
-        match visitor.f_down(self)? {
-            TreeNodeRecursion::Continue => {
-                handle_visit_recursion!(
-                    self.apply_children(&mut |n| n.visit(visitor))?,
-                    UP
-                );
-                visitor.f_up(self)
-            }
-            TreeNodeRecursion::Jump => visitor.f_up(self),
-            TreeNodeRecursion::Stop => Ok(TreeNodeRecursion::Stop),
-        }
+        visitor
+            .f_down(self)?
+            .visit_children(|| self.apply_children(|c| c.visit(visitor)))?
+            .visit_parent(|| visitor.f_up(self))
     }
 
     /// Implements the [visitor 
pattern](https://en.wikipedia.org/wiki/Visitor_pattern) for
@@ -184,8 +134,7 @@ pub trait TreeNode: Sized {
         &self,
         f: &mut F,
     ) -> Result<TreeNodeRecursion> {
-        handle_visit_recursion!(f(self)?, DOWN);
-        self.apply_children(&mut |n| n.apply(f))
+        f(self)?.visit_children(|| self.apply_children(|c| c.apply(f)))
     }
 
     /// Convenience utility for writing optimizer rules: Recursively apply the
@@ -205,10 +154,7 @@ pub trait TreeNode: Sized {
         self,
         f: &F,
     ) -> Result<Transformed<Self>> {
-        f(self)?.try_transform_node_with(
-            |n| n.map_children(|c| c.transform_down(f)),
-            TreeNodeRecursion::Continue,
-        )
+        handle_transform_recursion_down!(f(self), |c| c.transform_down(f))
     }
 
     /// Convenience utility for writing optimizer rules: Recursively apply the
@@ -218,10 +164,7 @@ pub trait TreeNode: Sized {
         self,
         f: &mut F,
     ) -> Result<Transformed<Self>> {
-        f(self)?.try_transform_node_with(
-            |n| n.map_children(|c| c.transform_down_mut(f)),
-            TreeNodeRecursion::Continue,
-        )
+        handle_transform_recursion_down!(f(self), |c| c.transform_down_mut(f))
     }
 
     /// Convenience utility for writing optimizer rules: Recursively apply the
@@ -232,8 +175,7 @@ pub trait TreeNode: Sized {
         self,
         f: &F,
     ) -> Result<Transformed<Self>> {
-        self.map_children(|c| c.transform_up(f))?
-            .try_transform_node_with(f, TreeNodeRecursion::Jump)
+        handle_transform_recursion_up!(self, |c| c.transform_up(f), f)
     }
 
     /// Convenience utility for writing optimizer rules: Recursively apply the
@@ -244,8 +186,7 @@ pub trait TreeNode: Sized {
         self,
         f: &mut F,
     ) -> Result<Transformed<Self>> {
-        self.map_children(|c| c.transform_up_mut(f))?
-            .try_transform_node_with(f, TreeNodeRecursion::Jump)
+        handle_transform_recursion_up!(self, |c| c.transform_up_mut(f), f)
     }
 
     /// Transforms the tree using `f_down` while traversing the tree top-down
@@ -355,7 +296,7 @@ pub trait TreeNode: Sized {
     /// Apply the closure `F` to the node's children.
     fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
         &self,
-        f: &mut F,
+        f: F,
     ) -> Result<TreeNodeRecursion>;
 
     /// Apply transform `F` to the node's children. Note that the transform `F`
@@ -432,6 +373,45 @@ pub enum TreeNodeRecursion {
     Stop,
 }
 
+impl TreeNodeRecursion {
+    /// Continues visiting nodes with `f` depending on the current 
[`TreeNodeRecursion`]
+    /// value and the fact that `f` is visiting the current node's children.
+    pub fn visit_children<F: FnOnce() -> Result<TreeNodeRecursion>>(
+        self,
+        f: F,
+    ) -> Result<TreeNodeRecursion> {
+        match self {
+            TreeNodeRecursion::Continue => f(),
+            TreeNodeRecursion::Jump => Ok(TreeNodeRecursion::Continue),
+            TreeNodeRecursion::Stop => Ok(self),
+        }
+    }
+
+    /// Continues visiting nodes with `f` depending on the current 
[`TreeNodeRecursion`]
+    /// value and the fact that `f` is visiting the current node's sibling.
+    pub fn visit_sibling<F: FnOnce() -> Result<TreeNodeRecursion>>(
+        self,
+        f: F,
+    ) -> Result<TreeNodeRecursion> {
+        match self {
+            TreeNodeRecursion::Continue | TreeNodeRecursion::Jump => f(),
+            TreeNodeRecursion::Stop => Ok(self),
+        }
+    }
+
+    /// Continues visiting nodes with `f` depending on the current 
[`TreeNodeRecursion`]
+    /// value and the fact that `f` is visiting the current node's parent.
+    pub fn visit_parent<F: FnOnce() -> Result<TreeNodeRecursion>>(
+        self,
+        f: F,
+    ) -> Result<TreeNodeRecursion> {
+        match self {
+            TreeNodeRecursion::Continue => f(),
+            TreeNodeRecursion::Jump | TreeNodeRecursion::Stop => Ok(self),
+        }
+    }
+}
+
 /// This struct is used by tree transformation APIs such as
 /// - [`TreeNode::rewrite`],
 /// - [`TreeNode::transform_down`],
@@ -489,15 +469,23 @@ impl<T> Transformed<T> {
         f(self.data).map(|data| Transformed::new(data, self.transformed, 
self.tnr))
     }
 
-    /// Handling [`TreeNodeRecursion::Continue`] and 
[`TreeNodeRecursion::Stop`]
-    /// is straightforward, but [`TreeNodeRecursion::Jump`] can behave 
differently
-    /// when we are traversing down or up on a tree. If [`TreeNodeRecursion`] 
of
-    /// the node is [`TreeNodeRecursion::Jump`], recursion stops with the given
-    /// `return_if_jump` value.
-    fn try_transform_node_with<F: FnOnce(T) -> Result<Transformed<T>>>(
+    /// Maps the [`Transformed`] object to the result of the given `f`.
+    pub fn transform_data<U, F: FnOnce(T) -> Result<Transformed<U>>>(
+        self,
+        f: F,
+    ) -> Result<Transformed<U>> {
+        f(self.data).map(|mut t| {
+            t.transformed |= self.transformed;
+            t
+        })
+    }
+
+    /// Maps the [`Transformed`] object to the result of the given `f` 
depending on the
+    /// current [`TreeNodeRecursion`] value and the fact that `f` is changing 
the current
+    /// node's children.
+    pub fn transform_children<F: FnOnce(T) -> Result<Transformed<T>>>(
         mut self,
         f: F,
-        return_if_jump: TreeNodeRecursion,
     ) -> Result<Transformed<T>> {
         match self.tnr {
             TreeNodeRecursion::Continue => {
@@ -507,37 +495,67 @@ impl<T> Transformed<T> {
                 });
             }
             TreeNodeRecursion::Jump => {
-                self.tnr = return_if_jump;
+                self.tnr = TreeNodeRecursion::Continue;
             }
             TreeNodeRecursion::Stop => {}
         }
         Ok(self)
     }
 
-    /// If [`TreeNodeRecursion`] of the node is 
[`TreeNodeRecursion::Continue`] or
-    /// [`TreeNodeRecursion::Jump`], transformation is applied to the node.
-    /// Otherwise, it remains as it is.
-    pub fn try_transform_node<F: FnOnce(T) -> Result<Transformed<T>>>(
+    /// Maps the [`Transformed`] object to the result of the given `f` 
depending on the
+    /// current [`TreeNodeRecursion`] value and the fact that `f` is changing 
the current
+    /// node's sibling.
+    pub fn transform_sibling<F: FnOnce(T) -> Result<Transformed<T>>>(
         self,
         f: F,
     ) -> Result<Transformed<T>> {
-        if self.tnr == TreeNodeRecursion::Stop {
-            Ok(self)
-        } else {
-            f(self.data).map(|mut t| {
+        match self.tnr {
+            TreeNodeRecursion::Continue | TreeNodeRecursion::Jump => {
+                f(self.data).map(|mut t| {
+                    t.transformed |= self.transformed;
+                    t
+                })
+            }
+            TreeNodeRecursion::Stop => Ok(self),
+        }
+    }
+
+    /// Maps the [`Transformed`] object to the result of the given `f` 
depending on the
+    /// current [`TreeNodeRecursion`] value and the fact that `f` is changing 
the current
+    /// node's parent.
+    pub fn transform_parent<F: FnOnce(T) -> Result<Transformed<T>>>(
+        self,
+        f: F,
+    ) -> Result<Transformed<T>> {
+        match self.tnr {
+            TreeNodeRecursion::Continue => f(self.data).map(|mut t| {
                 t.transformed |= self.transformed;
                 t
-            })
+            }),
+            TreeNodeRecursion::Jump | TreeNodeRecursion::Stop => Ok(self),
         }
     }
 }
 
 /// Transformation helper to process a sequence of iterable tree nodes that 
are siblings.
-pub trait TransformedIterator: Iterator {
+pub trait TreeNodeIterator: Iterator {
     /// Apples `f` to each item in this iterator
     ///
     /// Visits all items in the iterator unless
-    /// `f` returns an error or `f` returns TreeNodeRecursion::stop.
+    /// `f` returns an error or `f` returns `TreeNodeRecursion::Stop`.
+    ///
+    /// # Returns
+    /// Error if `f` returns an error or `Ok(TreeNodeRecursion)` from the last 
invocation
+    /// of `f` or `Continue` if the iterator is empty
+    fn apply_until_stop<F: FnMut(Self::Item) -> Result<TreeNodeRecursion>>(
+        self,
+        f: F,
+    ) -> Result<TreeNodeRecursion>;
+
+    /// Apples `f` to each item in this iterator
+    ///
+    /// Visits all items in the iterator unless
+    /// `f` returns an error or `f` returns `TreeNodeRecursion::Stop`.
     ///
     /// # Returns
     /// Error if `f` returns an error
@@ -554,7 +572,22 @@ pub trait TransformedIterator: Iterator {
     ) -> Result<Transformed<Vec<Self::Item>>>;
 }
 
-impl<I: Iterator> TransformedIterator for I {
+impl<I: Iterator> TreeNodeIterator for I {
+    fn apply_until_stop<F: FnMut(Self::Item) -> Result<TreeNodeRecursion>>(
+        self,
+        mut f: F,
+    ) -> Result<TreeNodeRecursion> {
+        let mut tnr = TreeNodeRecursion::Continue;
+        for i in self {
+            tnr = f(i)?;
+            match tnr {
+                TreeNodeRecursion::Continue | TreeNodeRecursion::Jump => {}
+                TreeNodeRecursion::Stop => return Ok(TreeNodeRecursion::Stop),
+            }
+        }
+        Ok(tnr)
+    }
+
     fn map_until_stop_and_collect<
         F: FnMut(Self::Item) -> Result<Transformed<Self::Item>>,
     >(
@@ -580,7 +613,7 @@ impl<I: Iterator> TransformedIterator for I {
 
 /// Transformation helper to process a heterogeneous sequence of tree node 
containing
 /// expressions.
-/// This macro is very similar to 
[TransformedIterator::map_until_stop_and_collect] to
+/// This macro is very similar to 
[TreeNodeIterator::map_until_stop_and_collect] to
 /// process nodes that are siblings, but it accepts an initial transformation 
(`F0`) and
 /// a sequence of pairs. Each pair is made of an expression (`EXPR`) and its
 /// transformation (`F`).
@@ -664,14 +697,9 @@ pub trait DynTreeNode {
 impl<T: DynTreeNode + ?Sized> TreeNode for Arc<T> {
     fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
         &self,
-        f: &mut F,
+        f: F,
     ) -> Result<TreeNodeRecursion> {
-        let mut tnr = TreeNodeRecursion::Continue;
-        for child in self.arc_children() {
-            tnr = f(&child)?;
-            handle_visit_recursion!(tnr)
-        }
-        Ok(tnr)
+        self.arc_children().iter().apply_until_stop(f)
     }
 
     fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
@@ -714,14 +742,9 @@ pub trait ConcreteTreeNode: Sized {
 impl<T: ConcreteTreeNode> TreeNode for T {
     fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
         &self,
-        f: &mut F,
+        f: F,
     ) -> Result<TreeNodeRecursion> {
-        let mut tnr = TreeNodeRecursion::Continue;
-        for child in self.children() {
-            tnr = f(child)?;
-            handle_visit_recursion!(tnr)
-        }
-        Ok(tnr)
+        self.children().into_iter().apply_until_stop(f)
     }
 
     fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
@@ -745,7 +768,7 @@ mod tests {
     use std::fmt::Display;
 
     use crate::tree_node::{
-        Transformed, TransformedIterator, TreeNode, TreeNodeRecursion, 
TreeNodeRewriter,
+        Transformed, TreeNode, TreeNodeIterator, TreeNodeRecursion, 
TreeNodeRewriter,
         TreeNodeVisitor,
     };
     use crate::Result;
@@ -763,22 +786,17 @@ mod tests {
     }
 
     impl<T> TreeNode for TestTreeNode<T> {
-        fn apply_children<F>(&self, f: &mut F) -> Result<TreeNodeRecursion>
-        where
-            F: FnMut(&Self) -> Result<TreeNodeRecursion>,
-        {
-            let mut tnr = TreeNodeRecursion::Continue;
-            for child in &self.children {
-                tnr = f(child)?;
-                handle_visit_recursion!(tnr);
-            }
-            Ok(tnr)
+        fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
+            &self,
+            f: F,
+        ) -> Result<TreeNodeRecursion> {
+            self.children.iter().apply_until_stop(f)
         }
 
-        fn map_children<F>(self, f: F) -> Result<Transformed<Self>>
-        where
-            F: FnMut(Self) -> Result<Transformed<Self>>,
-        {
+        fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
+            self,
+            f: F,
+        ) -> Result<Transformed<Self>> {
             Ok(self
                 .children
                 .into_iter()
diff --git a/datafusion/expr/src/tree_node/expr.rs 
b/datafusion/expr/src/tree_node/expr.rs
index df1585e5a5..97331720ce 100644
--- a/datafusion/expr/src/tree_node/expr.rs
+++ b/datafusion/expr/src/tree_node/expr.rs
@@ -25,16 +25,14 @@ use crate::expr::{
 use crate::{Expr, GetFieldAccess};
 
 use datafusion_common::tree_node::{
-    Transformed, TransformedIterator, TreeNode, TreeNodeRecursion,
-};
-use datafusion_common::{
-    handle_visit_recursion, internal_err, map_until_stop_and_collect, Result,
+    Transformed, TreeNode, TreeNodeIterator, TreeNodeRecursion,
 };
+use datafusion_common::{internal_err, map_until_stop_and_collect, Result};
 
 impl TreeNode for Expr {
     fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
         &self,
-        f: &mut F,
+        f: F,
     ) -> Result<TreeNodeRecursion> {
         let children = match self {
             Expr::Alias(Alias{expr,..})
@@ -133,19 +131,13 @@ impl TreeNode for Expr {
             }
         };
 
-        let mut tnr = TreeNodeRecursion::Continue;
-        for child in children {
-            tnr = f(child)?;
-            handle_visit_recursion!(tnr, DOWN);
-        }
-
-        Ok(tnr)
+        children.into_iter().apply_until_stop(f)
     }
 
-    fn map_children<F>(self, mut f: F) -> Result<Transformed<Self>>
-    where
-        F: FnMut(Self) -> Result<Transformed<Self>>,
-    {
+    fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
+        self,
+        mut f: F,
+    ) -> Result<Transformed<Self>> {
         Ok(match self {
             Expr::Column(_)
             | Expr::Wildcard { .. }
diff --git a/datafusion/expr/src/tree_node/plan.rs 
b/datafusion/expr/src/tree_node/plan.rs
index 02d5d18512..7a6b1005fe 100644
--- a/datafusion/expr/src/tree_node/plan.rs
+++ b/datafusion/expr/src/tree_node/plan.rs
@@ -20,9 +20,9 @@
 use crate::LogicalPlan;
 
 use datafusion_common::tree_node::{
-    Transformed, TransformedIterator, TreeNode, TreeNodeRecursion, 
TreeNodeVisitor,
+    Transformed, TreeNode, TreeNodeIterator, TreeNodeRecursion, 
TreeNodeVisitor,
 };
-use datafusion_common::{handle_visit_recursion, Result};
+use datafusion_common::Result;
 
 impl TreeNode for LogicalPlan {
     fn apply<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
@@ -31,9 +31,10 @@ impl TreeNode for LogicalPlan {
     ) -> Result<TreeNodeRecursion> {
         // Compared to the default implementation, we need to invoke
         // [`Self::apply_subqueries`] before visiting its children
-        handle_visit_recursion!(f(self)?, DOWN);
-        self.apply_subqueries(f)?;
-        self.apply_children(&mut |n| n.apply(f))
+        f(self)?.visit_children(|| {
+            self.apply_subqueries(f)?;
+            self.apply_children(|n| n.apply(f))
+        })
     }
 
     /// To use, define a struct that implements the trait [`TreeNodeVisitor`] 
and then invoke
@@ -62,39 +63,26 @@ impl TreeNode for LogicalPlan {
     ) -> Result<TreeNodeRecursion> {
         // Compared to the default implementation, we need to invoke
         // [`Self::visit_subqueries`] before visiting its children
-        match visitor.f_down(self)? {
-            TreeNodeRecursion::Continue => {
+        visitor
+            .f_down(self)?
+            .visit_children(|| {
                 self.visit_subqueries(visitor)?;
-                handle_visit_recursion!(
-                    self.apply_children(&mut |n| n.visit(visitor))?,
-                    UP
-                );
-                visitor.f_up(self)
-            }
-            TreeNodeRecursion::Jump => {
-                self.visit_subqueries(visitor)?;
-                visitor.f_up(self)
-            }
-            TreeNodeRecursion::Stop => Ok(TreeNodeRecursion::Stop),
-        }
+                self.apply_children(|n| n.visit(visitor))
+            })?
+            .visit_parent(|| visitor.f_up(self))
     }
 
     fn apply_children<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
         &self,
-        f: &mut F,
+        f: F,
     ) -> Result<TreeNodeRecursion> {
-        let mut tnr = TreeNodeRecursion::Continue;
-        for child in self.inputs() {
-            tnr = f(child)?;
-            handle_visit_recursion!(tnr, DOWN)
-        }
-        Ok(tnr)
+        self.inputs().into_iter().apply_until_stop(f)
     }
 
-    fn map_children<F>(self, f: F) -> Result<Transformed<Self>>
-    where
-        F: FnMut(Self) -> Result<Transformed<Self>>,
-    {
+    fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
+        self,
+        f: F,
+    ) -> Result<Transformed<Self>> {
         let new_children = self
             .inputs()
             .iter()
diff --git a/datafusion/optimizer/src/analyzer/subquery.rs 
b/datafusion/optimizer/src/analyzer/subquery.rs
index b7f513727d..038361c3ee 100644
--- a/datafusion/optimizer/src/analyzer/subquery.rs
+++ b/datafusion/optimizer/src/analyzer/subquery.rs
@@ -146,7 +146,7 @@ fn check_inner_plan(
     // We want to support as many operators as possible inside the correlated 
subquery
     match inner_plan {
         LogicalPlan::Aggregate(_) => {
-            inner_plan.apply_children(&mut |plan| {
+            inner_plan.apply_children(|plan| {
                 check_inner_plan(plan, is_scalar, true, 
can_contain_outer_ref)?;
                 Ok(TreeNodeRecursion::Continue)
             })?;
@@ -171,7 +171,7 @@ fn check_inner_plan(
         }
         LogicalPlan::Window(window) => {
             check_mixed_out_refer_in_window(window)?;
-            inner_plan.apply_children(&mut |plan| {
+            inner_plan.apply_children(|plan| {
                 check_inner_plan(plan, is_scalar, is_aggregate, 
can_contain_outer_ref)?;
                 Ok(TreeNodeRecursion::Continue)
             })?;
@@ -188,7 +188,7 @@ fn check_inner_plan(
         | LogicalPlan::Values(_)
         | LogicalPlan::Subquery(_)
         | LogicalPlan::SubqueryAlias(_) => {
-            inner_plan.apply_children(&mut |plan| {
+            inner_plan.apply_children(|plan| {
                 check_inner_plan(plan, is_scalar, is_aggregate, 
can_contain_outer_ref)?;
                 Ok(TreeNodeRecursion::Continue)
             })?;
@@ -201,7 +201,7 @@ fn check_inner_plan(
             ..
         }) => match join_type {
             JoinType::Inner => {
-                inner_plan.apply_children(&mut |plan| {
+                inner_plan.apply_children(|plan| {
                     check_inner_plan(
                         plan,
                         is_scalar,
@@ -221,7 +221,7 @@ fn check_inner_plan(
                 check_inner_plan(right, is_scalar, is_aggregate, 
can_contain_outer_ref)
             }
             JoinType::Full => {
-                inner_plan.apply_children(&mut |plan| {
+                inner_plan.apply_children(|plan| {
                     check_inner_plan(plan, is_scalar, is_aggregate, false)?;
                     Ok(TreeNodeRecursion::Continue)
                 })?;

Reply via email to