diff --git a/crates/cairo-lang-lowering/src/optimizations/const_folding.rs b/crates/cairo-lang-lowering/src/optimizations/const_folding.rs index 46980a110e2..ff7cd7c0562 100644 --- a/crates/cairo-lang-lowering/src/optimizations/const_folding.rs +++ b/crates/cairo-lang-lowering/src/optimizations/const_folding.rs @@ -1325,10 +1325,12 @@ impl<'db, 'mt> ConstFoldingContext<'db, 'mt> { let var_info = self.var_info.get(&info.inputs[0].var_id)?; let desnapped = try_extract_matches!(var_info.as_ref(), VarInfo::Snapshot)?; let element_var_infos = try_extract_matches!(desnapped.as_ref(), VarInfo::Array)?; - // TODO(orizi): Propagate success values as well. if element_var_infos.is_empty() { let arm = &info.arms[1]; - self.var_info.insert(arm.var_ids[0], VarInfo::Array(vec![]).into()); + self.var_info.insert( + arm.var_ids[0], + VarInfo::Snapshot(VarInfo::Array(vec![]).into()).into(), + ); Some(BlockEnd::Goto( arm.block_id, VarRemapping { @@ -1336,6 +1338,23 @@ impl<'db, 'mt> ConstFoldingContext<'db, 'mt> { }, )) } else { + let (remaining, popped) = if id == self.array_snapshot_pop_front { + (element_var_infos[1..].to_vec(), element_var_infos[0].clone()) + } else { + let split_idx = element_var_infos.len() - 1; + (element_var_infos[..split_idx].to_vec(), element_var_infos[split_idx].clone()) + }; + let arm = &info.arms[0]; + self.var_info.insert( + arm.var_ids[0], + VarInfo::Snapshot(VarInfo::Array(remaining).into()).into(), + ); + if let Some(popped) = popped { + self.var_info.insert( + arm.var_ids[1], + VarInfo::Box(VarInfo::Snapshot(popped).into()).into(), + ); + } None } } else { diff --git a/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding b/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding index 40cf443fb0d..1198ac981fc 100644 --- a/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding +++ b/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding @@ -6075,6 +6075,123 @@ End: //! > ========================================================================== +//! > Span pop_front success propagates remaining snapshot. + +//! > test_runner_name +test_match_optimizer + +//! > function_code +fn foo() -> Option> { + let mut snapshot = array![1].span().snapshot; + if let Some(_) = array_snapshot_pop_front(ref snapshot) { + return array_snapshot_pop_front(ref snapshot); + } + None +} + +//! > function_name +foo + +//! > module_code +use core::array::array_snapshot_pop_front; + +//! > semantic_diagnostics + +//! > before +Parameters: +blk0 (root): +Statements: + (v0: core::array::Array::) <- core::array::array_new::() + (v1: core::felt252) <- 1 + (v2: core::array::Array::) <- core::array::array_append::(v0, v1) + (v3: core::array::Array::, v4: @core::array::Array::) <- snapshot(v2) +End: + Match(match core::array::array_snapshot_pop_front::(v4) { + Option::Some(v5, v6) => blk1, + Option::None(v7) => blk5, + }) + +blk1: +Statements: +End: + Match(match core::array::array_snapshot_pop_front::(v5) { + Option::Some(v8, v9) => blk2, + Option::None(v10) => blk3, + }) + +blk2: +Statements: + (v11: core::option::Option::>) <- Option::Some(v9) +End: + Goto(blk4, {v11 -> v12}) + +blk3: +Statements: + (v13: ()) <- struct_construct() + (v14: core::option::Option::>) <- Option::None(v13) +End: + Goto(blk4, {v14 -> v12}) + +blk4: +Statements: +End: + Return(v12) + +blk5: +Statements: + (v15: ()) <- struct_construct() + (v16: core::option::Option::>) <- Option::None(v15) +End: + Return(v16) + +//! > after +Parameters: +blk0 (root): +Statements: + (v0: core::array::Array::) <- core::array::array_new::() + (v1: core::felt252) <- 1 + (v2: core::array::Array::) <- core::array::array_append::(v0, v1) + (v3: core::array::Array::, v4: @core::array::Array::) <- snapshot(v2) +End: + Match(match core::array::array_snapshot_pop_front::(v4) { + Option::Some(v5, v6) => blk1, + Option::None(v7) => blk5, + }) + +blk1: +Statements: +End: + Goto(blk3, {v5 -> v10}) + +blk2: +Statements: + (v11: core::option::Option::>) <- Option::Some(v9) +End: + Goto(blk4, {v11 -> v12}) + +blk3: +Statements: + (v13: ()) <- struct_construct() + (v14: core::option::Option::>) <- Option::None(v13) +End: + Goto(blk4, {v14 -> v12}) + +blk4: +Statements: +End: + Return(v12) + +blk5: +Statements: + (v15: ()) <- struct_construct() + (v16: core::option::Option::>) <- Option::None(v15) +End: + Return(v16) + +//! > lowering_diagnostics + +//! > ========================================================================== + //! > Panic with byte array value. //! > test_runner_name