@@ -14,7 +14,9 @@ use cairo_lang_utils::ordered_hash_map::{Entry, OrderedHashMap};
1414use cairo_lang_utils:: ordered_hash_set:: OrderedHashSet ;
1515use salsa:: Database ;
1616
17+ use super :: var_renamer:: VarRenamer ;
1718use crate :: borrow_check:: analysis:: StatementLocation ;
19+ use crate :: utils:: RebuilderEx ;
1820use crate :: {
1921 BlockEnd , Lowered , Statement , StatementStructDestructure , VarUsage , Variable , VariableArena ,
2022 VariableId ,
@@ -183,8 +185,30 @@ pub fn apply_reboxing_candidates<'db>(
183185
184186 trace ! ( "Applying {} reboxing optimization(s)." , candidates. len( ) ) ;
185187
188+ let mut renamer = VarRenamer :: default ( ) ;
189+ let mut stmts_to_remove = Vec :: new ( ) ;
190+
186191 for candidate in candidates {
187- apply_reboxing_candidate ( db, lowered, candidate) ;
192+ match & candidate. source {
193+ ReboxingValue :: Revoked => { }
194+ ReboxingValue :: Unboxed ( id) => {
195+ renamer. renamed_vars . insert ( candidate. reboxed_var , * id) ;
196+ stmts_to_remove. push ( candidate. into_box_location ) ;
197+ }
198+ ReboxingValue :: MemberOfUnboxed { source, member } => {
199+ replace_into_box_call ( db, lowered, candidate, source, * member) ;
200+ }
201+ }
202+ }
203+
204+ // We sort the candidates such that removal of statements can be done in reverse order.
205+ stmts_to_remove. sort_by_key ( |( block_id, stmt_idx) | ( block_id. 0 , * stmt_idx) ) ;
206+ for ( block_id, stmt_idx) in stmts_to_remove. into_iter ( ) . rev ( ) {
207+ lowered. blocks [ block_id] . statements . remove ( stmt_idx) ;
208+ }
209+
210+ for block in lowered. blocks . iter_mut ( ) {
211+ * block = renamer. rebuild_block ( block) ;
188212 }
189213}
190214
@@ -203,25 +227,14 @@ pub fn apply_reboxing<'db>(db: &'db dyn Database, lowered: &mut Lowered<'db>) {
203227 }
204228}
205229
206- /// Applies a single reboxing optimization for the given candidate .
207- fn apply_reboxing_candidate < ' db > (
230+ /// Replaces the call to `into_box` with a call to `struct_boxed_deconstruct` .
231+ fn replace_into_box_call < ' db > (
208232 db : & ' db dyn Database ,
209233 lowered : & mut Lowered < ' db > ,
210234 candidate : & ReboxCandidate ,
235+ source : & Rc < ReboxingValue > ,
236+ member : usize ,
211237) {
212- trace ! (
213- "Applying optimization: candidate={}, reboxed={}" ,
214- candidate. source,
215- candidate. reboxed_var. index( )
216- ) ;
217-
218- // TODO(eytan-starkware): Handle snapshot of box (e.g., @Box<T>).
219- // Only support MemberOfUnboxed where source is Unboxed for now.
220- let ReboxingValue :: MemberOfUnboxed { source, member } = & candidate. source else {
221- // If source is not member of unboxed, we are reboxing original value which is not supported
222- // yet.
223- return ;
224- } ;
225238 let ReboxingValue :: Unboxed ( source_var) = * * source else {
226239 // When source of the value is not `Unboxes`, it is a nested MemberOfUnboxed, which is not
227240 // supported yet.
@@ -232,7 +245,7 @@ fn apply_reboxing_candidate<'db>(
232245 db,
233246 & mut lowered. variables ,
234247 source_var,
235- * member,
248+ member,
236249 candidate. reboxed_var ,
237250 & lowered. blocks [ candidate. into_box_location . 0 ] . statements [ candidate. into_box_location . 1 ] ,
238251 ) {
0 commit comments