@@ -386,82 +386,91 @@ fn ever_initialized_map(
386386 fn dfs (
387387 db : & dyn HirDatabase ,
388388 body : & MirBody ,
389- b : BasicBlockId ,
390389 l : LocalId ,
390+ stack : & mut Vec < BasicBlockId > ,
391391 result : & mut ArenaMap < BasicBlockId , ArenaMap < LocalId , bool > > ,
392392 ) {
393- let mut is_ever_initialized = result[ b] [ l] ; // It must be filled, as we use it as mark for dfs
394- let block = & body. basic_blocks [ b] ;
395- for statement in & block. statements {
396- match & statement. kind {
397- StatementKind :: Assign ( p, _) => {
398- if p. projection . lookup ( & body. projection_store ) . is_empty ( ) && p. local == l {
399- is_ever_initialized = true ;
393+ while let Some ( b) = stack. pop ( ) {
394+ let mut is_ever_initialized = result[ b] [ l] ; // It must be filled, as we use it as mark for dfs
395+ let block = & body. basic_blocks [ b] ;
396+ for statement in & block. statements {
397+ match & statement. kind {
398+ StatementKind :: Assign ( p, _) => {
399+ if p. projection . lookup ( & body. projection_store ) . is_empty ( ) && p. local == l {
400+ is_ever_initialized = true ;
401+ }
400402 }
401- }
402- StatementKind :: StorageDead ( p ) => {
403- if * p == l {
404- is_ever_initialized = false ;
403+ StatementKind :: StorageDead ( p ) => {
404+ if * p == l {
405+ is_ever_initialized = false ;
406+ }
405407 }
408+ StatementKind :: Deinit ( _)
409+ | StatementKind :: FakeRead ( _)
410+ | StatementKind :: Nop
411+ | StatementKind :: StorageLive ( _) => ( ) ,
406412 }
407- StatementKind :: Deinit ( _)
408- | StatementKind :: FakeRead ( _)
409- | StatementKind :: Nop
410- | StatementKind :: StorageLive ( _) => ( ) ,
411- }
412- }
413- let Some ( terminator) = & block. terminator else {
414- never ! (
415- "Terminator should be none only in construction.\n The body:\n {}" ,
416- body. pretty_print( db)
417- ) ;
418- return ;
419- } ;
420- let mut process = |target, is_ever_initialized| {
421- if !result[ target] . contains_idx ( l) || !result[ target] [ l] && is_ever_initialized {
422- result[ target] . insert ( l, is_ever_initialized) ;
423- dfs ( db, body, target, l, result) ;
424- }
425- } ;
426- match & terminator. kind {
427- TerminatorKind :: Goto { target } => process ( * target, is_ever_initialized) ,
428- TerminatorKind :: SwitchInt { targets, .. } => {
429- targets. all_targets ( ) . iter ( ) . for_each ( |& it| process ( it, is_ever_initialized) ) ;
430413 }
431- TerminatorKind :: UnwindResume
432- | TerminatorKind :: Abort
433- | TerminatorKind :: Return
434- | TerminatorKind :: Unreachable => ( ) ,
435- TerminatorKind :: Call { target, cleanup, destination, .. } => {
436- if destination. projection . lookup ( & body. projection_store ) . is_empty ( )
437- && destination. local == l
438- {
439- is_ever_initialized = true ;
414+ let Some ( terminator) = & block. terminator else {
415+ never ! (
416+ "Terminator should be none only in construction.\n The body:\n {}" ,
417+ body. pretty_print( db)
418+ ) ;
419+ return ;
420+ } ;
421+ let mut process = |target, is_ever_initialized| {
422+ if !result[ target] . contains_idx ( l) || !result[ target] [ l] && is_ever_initialized {
423+ result[ target] . insert ( l, is_ever_initialized) ;
424+ stack. push ( target) ;
425+ }
426+ } ;
427+ match & terminator. kind {
428+ TerminatorKind :: Goto { target } => process ( * target, is_ever_initialized) ,
429+ TerminatorKind :: SwitchInt { targets, .. } => {
430+ targets. all_targets ( ) . iter ( ) . for_each ( |& it| process ( it, is_ever_initialized) ) ;
431+ }
432+ TerminatorKind :: UnwindResume
433+ | TerminatorKind :: Abort
434+ | TerminatorKind :: Return
435+ | TerminatorKind :: Unreachable => ( ) ,
436+ TerminatorKind :: Call { target, cleanup, destination, .. } => {
437+ if destination. projection . lookup ( & body. projection_store ) . is_empty ( )
438+ && destination. local == l
439+ {
440+ is_ever_initialized = true ;
441+ }
442+ target. iter ( ) . chain ( cleanup) . for_each ( |& it| process ( it, is_ever_initialized) ) ;
443+ }
444+ TerminatorKind :: Drop { target, unwind, place : _ } => {
445+ iter:: once ( target)
446+ . chain ( unwind)
447+ . for_each ( |& it| process ( it, is_ever_initialized) ) ;
448+ }
449+ TerminatorKind :: DropAndReplace { .. }
450+ | TerminatorKind :: Assert { .. }
451+ | TerminatorKind :: Yield { .. }
452+ | TerminatorKind :: CoroutineDrop
453+ | TerminatorKind :: FalseEdge { .. }
454+ | TerminatorKind :: FalseUnwind { .. } => {
455+ never ! ( "We don't emit these MIR terminators yet" ) ;
440456 }
441- target. iter ( ) . chain ( cleanup) . for_each ( |& it| process ( it, is_ever_initialized) ) ;
442- }
443- TerminatorKind :: Drop { target, unwind, place : _ } => {
444- iter:: once ( target) . chain ( unwind) . for_each ( |& it| process ( it, is_ever_initialized) ) ;
445- }
446- TerminatorKind :: DropAndReplace { .. }
447- | TerminatorKind :: Assert { .. }
448- | TerminatorKind :: Yield { .. }
449- | TerminatorKind :: CoroutineDrop
450- | TerminatorKind :: FalseEdge { .. }
451- | TerminatorKind :: FalseUnwind { .. } => {
452- never ! ( "We don't emit these MIR terminators yet" ) ;
453457 }
454458 }
455459 }
460+ let mut stack = Vec :: new ( ) ;
456461 for & l in & body. param_locals {
457462 result[ body. start_block ] . insert ( l, true ) ;
458- dfs ( db, body, body. start_block , l, & mut result) ;
463+ stack. clear ( ) ;
464+ stack. push ( body. start_block ) ;
465+ dfs ( db, body, l, & mut stack, & mut result) ;
459466 }
460467 for l in body. locals . iter ( ) . map ( |it| it. 0 ) {
461468 db. unwind_if_cancelled ( ) ;
462469 if !result[ body. start_block ] . contains_idx ( l) {
463470 result[ body. start_block ] . insert ( l, false ) ;
464- dfs ( db, body, body. start_block , l, & mut result) ;
471+ stack. clear ( ) ;
472+ stack. push ( body. start_block ) ;
473+ dfs ( db, body, l, & mut stack, & mut result) ;
465474 }
466475 }
467476 result
0 commit comments