diff --git a/vortex-array/src/arrays/scalar_fn/vtable/validity.rs b/vortex-array/src/arrays/scalar_fn/vtable/validity.rs index 39ab8c2c466..4e8ab0c95c0 100644 --- a/vortex-array/src/arrays/scalar_fn/vtable/validity.rs +++ b/vortex-array/src/arrays/scalar_fn/vtable/validity.rs @@ -21,7 +21,6 @@ use crate::legacy_session; use crate::scalar_fn::TypedScalarFnInstance; use crate::scalar_fn::VecExecutionArgs; use crate::scalar_fn::fns::literal::Literal; -use crate::scalar_fn::fns::root::Root; use crate::validity::Validity; /// Execute an expression tree recursively. @@ -32,10 +31,10 @@ fn execute_expr( row_count: usize, ctx: &mut ExecutionCtx, ) -> VortexResult { - // Handle Root expression - this should not happen in validity expressions - if expr.is::() { - vortex_bail!("Root expression cannot be executed in validity context"); - } + // Only Expression::Scalar is executable + let Some(scalar_fn) = expr.as_scalar() else { + vortex_bail!("Only Expression::Scalar is executable"); + }; // Handle Literal expression - create a constant array if expr.is::() { @@ -52,7 +51,7 @@ fn execute_expr( let args = VecExecutionArgs::new(inputs, row_count); - Ok(expr.scalar_fn().execute(&args, ctx)?.into_array()) + Ok(scalar_fn.execute(&args, ctx)?.into_array()) } impl ValidityVTable for ScalarFn { diff --git a/vortex-array/src/expr/analysis/fallible.rs b/vortex-array/src/expr/analysis/fallible.rs index b6d45bd5483..ff43d51603b 100644 --- a/vortex-array/src/expr/analysis/fallible.rs +++ b/vortex-array/src/expr/analysis/fallible.rs @@ -8,7 +8,11 @@ use crate::expr::label_tree; pub fn label_is_fallible(expr: &Expression) -> BooleanLabels<'_> { label_tree( expr, - |expr| expr.signature().is_fallible(), + |expr| match expr { + Expression::Scalar { scalar_fn, .. } => scalar_fn.signature().is_fallible(), + // The scope itself cannot fail. + Expression::Root => false, + }, |acc, &child| acc | child, ) } diff --git a/vortex-array/src/expr/analysis/immediate_access.rs b/vortex-array/src/expr/analysis/immediate_access.rs index fd720607284..6c2e4975a92 100644 --- a/vortex-array/src/expr/analysis/immediate_access.rs +++ b/vortex-array/src/expr/analysis/immediate_access.rs @@ -9,7 +9,6 @@ use crate::expr::BoundExpression; use crate::expr::Expression; use crate::expr::analysis::AnnotationFn; use crate::scalar_fn::fns::get_item::GetItem; -use crate::scalar_fn::fns::root::Root; use crate::scalar_fn::fns::select::Select; /// Returns the "free fields" for this expression node. @@ -26,9 +25,10 @@ use crate::scalar_fn::fns::select::Select; /// /// # Annotation Rules /// -/// - **[`Select`]**: Returns the included field names if the child is [`Root`]. -/// - **[`GetItem`] on [`Root`]**: Returns `[field_name]` if the child is [`Root`]. -/// - **[`Root`]**: Returns all field names from `scope` (conservative over-approximation). +/// - **[`Select`]**: Returns the included field names if the child is [`Expression::Root`]. +/// - **[`GetItem`] on the root**: Returns `[field_name]` if the child is [`Expression::Root`]. +/// - **[`Expression::Root`]**: Returns all field names from `scope` (conservative +/// over-approximation). /// - **Everything else**: Returns empty (annotations aggregate from children automatically). /// /// # Example @@ -42,7 +42,7 @@ pub fn make_free_field_annotator( ) -> impl AnnotationFn { move |expr: &Expression| { if let Some(selection) = expr.as_opt::