Skip to content

Commit dc6142e

Browse files
timsaucerclaude
andauthored
Remove as_any on the PhysicalExpr trait (apache#21573)
## Which issue does this PR close? - Addresses part of apache#21572 ## Rationale for this change This PR reduces the amount of boilerplate code that users need to write for Physical Expressions. ## What changes are included in this PR? Now that we have [trait upcasting](https://blog.rust-lang.org/2025/04/03/Rust-1.86.0/) since rust 1.86, we no longer need every implementation of this trait to have the as_any function that returns &self. This PR makes Any an supertrait and makes the appropriate casts when necessary. ## Are these changes tested? Existing unit tests. ## Are there any user-facing changes? Yes, the users simply need to remove the as_any function. The upgrade guide is updated. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 240fbdb commit dc6142e

File tree

80 files changed

+295
-724
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+295
-724
lines changed

datafusion-examples/examples/custom_data_source/custom_file_casts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl PhysicalExprAdapter for CustomCastsPhysicalExprAdapter {
185185
// kernel / expression. For example, DataFusion Comet has a custom cast
186186
// kernel in its native Spark expression implementation.
187187
expr.transform(|expr| {
188-
if let Some(cast) = expr.as_any().downcast_ref::<CastExpr>() {
188+
if let Some(cast) = expr.downcast_ref::<CastExpr>() {
189189
let input_data_type =
190190
cast.expr().data_type(&self.physical_file_schema)?;
191191
let output_data_type = cast.target_field().data_type();

datafusion-examples/examples/data_io/json_shredding.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,20 +311,16 @@ impl ShreddedJsonRewriter {
311311
expr: Arc<dyn PhysicalExpr>,
312312
physical_file_schema: &Schema,
313313
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
314-
if let Some(func) = expr.as_any().downcast_ref::<ScalarFunctionExpr>()
314+
if let Some(func) = expr.downcast_ref::<ScalarFunctionExpr>()
315315
&& func.name() == "json_get_str"
316316
&& func.args().len() == 2
317317
{
318318
// Get the key from the first argument
319-
if let Some(literal) = func.args()[0]
320-
.as_any()
321-
.downcast_ref::<expressions::Literal>()
319+
if let Some(literal) = func.args()[0].downcast_ref::<expressions::Literal>()
322320
&& let ScalarValue::Utf8(Some(field_name)) = literal.value()
323321
{
324322
// Get the column from the second argument
325-
if let Some(column) = func.args()[1]
326-
.as_any()
327-
.downcast_ref::<expressions::Column>()
323+
if let Some(column) = func.args()[1].downcast_ref::<expressions::Column>()
328324
{
329325
let column_name = column.name();
330326
// Check if there's a flat column with underscore prefix

datafusion-examples/examples/proto/expression_deduplication.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ pub async fn expression_deduplication() -> Result<()> {
129129
};
130130
let predicate = Arc::clone(filter_exec.predicate());
131131
let binary_expr = predicate
132-
.as_any()
133132
.downcast_ref::<BinaryExpr>()
134133
.expect("Predicate is not a BinaryExpr");
135134
let left = &binary_expr.left();

datafusion/core/src/datasource/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ mod tests {
167167
impl PhysicalExprAdapter for TestPhysicalExprAdapter {
168168
fn rewrite(&self, expr: Arc<dyn PhysicalExpr>) -> Result<Arc<dyn PhysicalExpr>> {
169169
expr.transform(|e| {
170-
if let Some(column) = e.as_any().downcast_ref::<Column>() {
170+
if let Some(column) = e.downcast_ref::<Column>() {
171171
// If column is "extra_column" and missing from physical schema, inject "foo"
172172
if column.name() == "extra_column"
173173
&& self.physical_file_schema.index_of("extra_column").is_err()

datafusion/core/tests/fuzz_cases/equivalence/utils.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn output_schema(
4949
let data_type = source.data_type(input_schema)?;
5050
let nullable = source.nullable(input_schema)?;
5151
for (target, _) in targets.iter() {
52-
let Some(column) = target.as_any().downcast_ref::<Column>() else {
52+
let Some(column) = target.downcast_ref::<Column>() else {
5353
return plan_err!("Expects to have column");
5454
};
5555
fields.push(Field::new(column.name(), data_type.clone(), nullable));
@@ -282,7 +282,7 @@ fn get_representative_arr(
282282
schema: SchemaRef,
283283
) -> Option<ArrayRef> {
284284
for expr in eq_group.iter() {
285-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
285+
let col = expr.downcast_ref::<Column>().unwrap();
286286
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
287287
if let Some(res) = &existing_vec[idx] {
288288
return Some(Arc::clone(res));
@@ -370,7 +370,7 @@ pub fn generate_table_for_eq_properties(
370370

371371
// Fill constant columns
372372
for constant in eq_properties.constants() {
373-
let col = constant.expr.as_any().downcast_ref::<Column>().unwrap();
373+
let col = constant.expr.downcast_ref::<Column>().unwrap();
374374
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
375375
let arr =
376376
Arc::new(Float64Array::from_iter_values(vec![0 as f64; n_elem])) as ArrayRef;
@@ -382,7 +382,7 @@ pub fn generate_table_for_eq_properties(
382382
let (sort_columns, indices): (Vec<_>, Vec<_>) = ordering
383383
.iter()
384384
.map(|PhysicalSortExpr { expr, options }| {
385-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
385+
let col = expr.downcast_ref::<Column>().unwrap();
386386
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
387387
let arr = generate_random_array(n_elem, n_distinct);
388388
(
@@ -408,7 +408,7 @@ pub fn generate_table_for_eq_properties(
408408
.unwrap_or_else(|| generate_random_array(n_elem, n_distinct));
409409

410410
for expr in eq_group.iter() {
411-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
411+
let col = expr.downcast_ref::<Column>().unwrap();
412412
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
413413
schema_vec[idx] = Some(Arc::clone(&representative_array));
414414
}

datafusion/core/tests/fuzz_cases/sort_preserving_repartition_fuzz.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ mod sp_repartition_fuzz_tests {
118118
schema: SchemaRef,
119119
) -> Option<ArrayRef> {
120120
for expr in eq_group.iter() {
121-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
121+
let col = expr.downcast_ref::<Column>().unwrap();
122122
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
123123
if let Some(res) = &existing_vec[idx] {
124124
return Some(res.clone());
@@ -149,7 +149,7 @@ mod sp_repartition_fuzz_tests {
149149

150150
// Fill constant columns
151151
for constant in eq_properties.constants() {
152-
let col = constant.expr.as_any().downcast_ref::<Column>().unwrap();
152+
let col = constant.expr.downcast_ref::<Column>().unwrap();
153153
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
154154
let arr =
155155
Arc::new(UInt64Array::from_iter_values(vec![0; n_elem])) as ArrayRef;
@@ -161,7 +161,7 @@ mod sp_repartition_fuzz_tests {
161161
let (sort_columns, indices): (Vec<_>, Vec<_>) = ordering
162162
.iter()
163163
.map(|PhysicalSortExpr { expr, options }| {
164-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
164+
let col = expr.downcast_ref::<Column>().unwrap();
165165
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
166166
let arr = generate_random_array(n_elem, n_distinct);
167167
(
@@ -187,7 +187,7 @@ mod sp_repartition_fuzz_tests {
187187
.unwrap_or_else(|| generate_random_array(n_elem, n_distinct));
188188

189189
for expr in eq_group.iter() {
190-
let col = expr.as_any().downcast_ref::<Column>().unwrap();
190+
let col = expr.downcast_ref::<Column>().unwrap();
191191
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
192192
schema_vec[idx] = Some(representative_array.clone());
193193
}

datafusion/core/tests/parquet/expr_adapter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl PhysicalExprAdapter for CustomPhysicalExprAdapter {
490490
fn rewrite(&self, mut expr: Arc<dyn PhysicalExpr>) -> Result<Arc<dyn PhysicalExpr>> {
491491
expr = expr
492492
.transform(|expr| {
493-
if let Some(column) = expr.as_any().downcast_ref::<Column>() {
493+
if let Some(column) = expr.downcast_ref::<Column>() {
494494
let field_name = column.name();
495495
if self
496496
.physical_file_schema

datafusion/core/tests/physical_optimizer/filter_pushdown.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2959,7 +2959,7 @@ async fn test_discover_dynamic_filters_via_expressions_api() {
29592959

29602960
// Check expressions from this node using apply_expressions
29612961
let _ = plan.apply_expressions(&mut |expr| {
2962-
if let Some(_df) = expr.as_any().downcast_ref::<DynamicFilterPhysicalExpr>() {
2962+
if let Some(_df) = expr.downcast_ref::<DynamicFilterPhysicalExpr>() {
29632963
count += 1;
29642964
}
29652965
Ok(TreeNodeRecursion::Continue)

datafusion/core/tests/physical_optimizer/join_selection.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,6 @@ async fn test_hash_join_swap_on_joins_with_projections(
759759

760760
fn assert_col_expr(expr: &Arc<dyn PhysicalExpr>, name: &str, index: usize) {
761761
let col = expr
762-
.as_any()
763762
.downcast_ref::<Column>()
764763
.expect("Projection items should be Column expression");
765764
assert_eq!(col.name(), name);

datafusion/core/tests/physical_optimizer/replace_with_order_preserving_variants.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,8 +1127,8 @@ fn hash_join_exec(
11271127
) -> Arc<dyn ExecutionPlan> {
11281128
let left_on = col("c", &left.schema()).unwrap();
11291129
let right_on = col("c", &right.schema()).unwrap();
1130-
let left_col = left_on.as_any().downcast_ref::<Column>().unwrap();
1131-
let right_col = right_on.as_any().downcast_ref::<Column>().unwrap();
1130+
let left_col = left_on.downcast_ref::<Column>().unwrap();
1131+
let right_col = right_on.downcast_ref::<Column>().unwrap();
11321132
Arc::new(
11331133
HashJoinExec::try_new(
11341134
left,

0 commit comments

Comments
 (0)