@@ -386,82 +386,91 @@ fn ever_initialized_map(
386
386
fn dfs(
387
387
db: &dyn HirDatabase,
388
388
body: &MirBody,
389
- b: BasicBlockId,
390
389
l: LocalId,
390
+ stack: &mut Vec<BasicBlockId>,
391
391
result: &mut ArenaMap<BasicBlockId, ArenaMap<LocalId, bool>>,
392
392
) {
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
+ }
400
402
}
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
+ }
405
407
}
408
+ StatementKind::Deinit(_)
409
+ | StatementKind::FakeRead(_)
410
+ | StatementKind::Nop
411
+ | StatementKind::StorageLive(_) => (),
406
412
}
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.\nThe 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));
430
413
}
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.\nThe 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");
440
456
}
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");
453
457
}
454
458
}
455
459
}
460
+ let mut stack = Vec::new();
456
461
for &l in &body.param_locals {
457
462
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);
459
466
}
460
467
for l in body.locals.iter().map(|it| it.0) {
461
468
db.unwind_if_cancelled();
462
469
if !result[body.start_block].contains_idx(l) {
463
470
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);
465
474
}
466
475
}
467
476
result
0 commit comments