|
17 | 17 | //! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker |
18 | 18 |
|
19 | 19 | use rustc_middle::mir::coverage::CoverageKind; |
20 | | -use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, TerminatorKind}; |
| 20 | +use rustc_middle::mir::*; |
21 | 21 | use rustc_middle::ty::TyCtxt; |
22 | 22 | use rustc_middle::ty::adjustment::PointerCoercion; |
23 | 23 |
|
24 | 24 | pub(super) struct CleanupPostBorrowck; |
25 | 25 |
|
26 | 26 | impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { |
27 | 27 | fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { |
28 | | - for basic_block in body.basic_blocks.as_mut() { |
| 28 | + let any_false_edge = body.basic_blocks.iter().any(|basic_block| { |
| 29 | + matches!( |
| 30 | + basic_block.terminator().kind, |
| 31 | + TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } |
| 32 | + ) |
| 33 | + }); |
| 34 | + |
| 35 | + let basic_blocks = if any_false_edge { |
| 36 | + body.basic_blocks.as_mut() |
| 37 | + } else { |
| 38 | + body.basic_blocks.as_mut_preserves_cfg() |
| 39 | + }; |
| 40 | + for basic_block in basic_blocks.iter_mut() { |
29 | 41 | for statement in basic_block.statements.iter_mut() { |
30 | 42 | match statement.kind { |
31 | 43 | StatementKind::AscribeUserType(..) |
@@ -59,10 +71,14 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { |
59 | 71 | _ => (), |
60 | 72 | } |
61 | 73 | } |
| 74 | + |
| 75 | + // If we change any terminator, we need to ensure that we invalidated the CFG cache. |
| 76 | + // This is tracked by `any_false_edge` flag above. |
62 | 77 | let terminator = basic_block.terminator_mut(); |
63 | 78 | match terminator.kind { |
64 | 79 | TerminatorKind::FalseEdge { real_target, .. } |
65 | 80 | | TerminatorKind::FalseUnwind { real_target, .. } => { |
| 81 | + debug_assert!(any_false_edge); |
66 | 82 | terminator.kind = TerminatorKind::Goto { target: real_target }; |
67 | 83 | } |
68 | 84 | _ => {} |
|
0 commit comments