summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/scope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build/scope.rs')
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs68
1 files changed, 49 insertions, 19 deletions
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 591b41633..f32d2db4e 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -86,12 +86,12 @@ use std::mem;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::HirId;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::thir::{Expr, LintLevel};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{DesugaringKind, Span, DUMMY_SP};
#[derive(Debug)]
pub struct Scopes<'tcx> {
@@ -360,7 +360,7 @@ impl DropTree {
fn link_blocks<'tcx>(
&self,
cfg: &mut CFG<'tcx>,
- blocks: &IndexVec<DropIdx, Option<BasicBlock>>,
+ blocks: &IndexSlice<DropIdx, Option<BasicBlock>>,
) {
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
let Some(block) = blocks[drop_idx] else { continue };
@@ -369,7 +369,7 @@ impl DropTree {
let terminator = TerminatorKind::Drop {
target: blocks[drop_data.1].unwrap(),
// The caller will handle this if needed.
- unwind: None,
+ unwind: UnwindAction::Terminate,
place: drop_data.0.local.into(),
};
cfg.terminate(block, drop_data.0.source_info, terminator);
@@ -1072,7 +1072,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. }
),
@@ -1118,24 +1117,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
/// Utility function for *non*-scope code to build their own drops
+ /// Force a drop at this point in the MIR by creating a new block.
pub(crate) fn build_drop_and_replace(
&mut self,
block: BasicBlock,
span: Span,
place: Place<'tcx>,
- value: Operand<'tcx>,
+ value: Rvalue<'tcx>,
) -> BlockAnd<()> {
+ let span = self.tcx.with_stable_hashing_context(|hcx| {
+ span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
+ });
let source_info = self.source_info(span);
- let next_target = self.cfg.start_new_block();
+
+ // create the new block for the assignment
+ let assign = self.cfg.start_new_block();
+ self.cfg.push_assign(assign, source_info, place, value.clone());
+
+ // create the new block for the assignment in the case of unwinding
+ let assign_unwind = self.cfg.start_new_cleanup_block();
+ self.cfg.push_assign(assign_unwind, source_info, place, value.clone());
self.cfg.terminate(
block,
source_info,
- TerminatorKind::DropAndReplace { place, value, target: next_target, unwind: None },
+ TerminatorKind::Drop {
+ place,
+ target: assign,
+ unwind: UnwindAction::Cleanup(assign_unwind),
+ },
);
self.diverge_from(block);
- next_target.unit()
+ assign.unit()
}
/// Creates an `Assert` terminator and return the success block.
@@ -1155,7 +1169,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.terminate(
block,
source_info,
- TerminatorKind::Assert { cond, expected, msg, target: success_block, cleanup: None },
+ TerminatorKind::Assert {
+ cond,
+ expected,
+ msg,
+ target: success_block,
+ unwind: UnwindAction::Continue,
+ },
);
self.diverge_from(block);
@@ -1234,7 +1254,11 @@ fn build_scope_drops<'tcx>(
cfg.terminate(
block,
source_info,
- TerminatorKind::Drop { place: local.into(), target: next, unwind: None },
+ TerminatorKind::Drop {
+ place: local.into(),
+ target: next,
+ unwind: UnwindAction::Continue,
+ },
);
block = next;
}
@@ -1413,18 +1437,24 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
let term = &mut cfg.block_data_mut(from).terminator_mut();
match &mut term.kind {
- TerminatorKind::Drop { unwind, .. }
- | TerminatorKind::DropAndReplace { unwind, .. }
- | TerminatorKind::FalseUnwind { unwind, .. }
- | TerminatorKind::Call { cleanup: unwind, .. }
- | TerminatorKind::Assert { cleanup: unwind, .. }
- | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {
- *unwind = Some(to);
+ TerminatorKind::Drop { unwind, .. } => {
+ if let UnwindAction::Cleanup(unwind) = *unwind {
+ let source_info = term.source_info;
+ cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
+ } else {
+ *unwind = UnwindAction::Cleanup(to);
+ }
+ }
+ TerminatorKind::FalseUnwind { unwind, .. }
+ | TerminatorKind::Call { unwind, .. }
+ | TerminatorKind::Assert { unwind, .. }
+ | TerminatorKind::InlineAsm { unwind, .. } => {
+ *unwind = UnwindAction::Cleanup(to);
}
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Yield { .. }