summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/generator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/generator.rs')
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs82
1 files changed, 52 insertions, 30 deletions
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 2e97312ee..4c4423721 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -70,10 +70,10 @@ use rustc_mir_dataflow::impls::{
};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{self, Analysis};
-use rustc_span::def_id::DefId;
+use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::symbol::sym;
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::spec::PanicStrategy;
use std::{iter, ops};
@@ -162,9 +162,10 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
place,
Place {
local: SELF_ARG,
- projection: self
- .tcx()
- .mk_place_elems(&[ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]),
+ projection: self.tcx().mk_place_elems(&[ProjectionElem::Field(
+ FieldIdx::new(0),
+ self.ref_gen_ty,
+ )]),
},
self.tcx,
);
@@ -273,7 +274,7 @@ impl<'tcx> TransformVisitor<'tcx> {
statements.push(Statement {
kind: StatementKind::Assign(Box::new((
Place::return_place(),
- Rvalue::Aggregate(Box::new(kind), vec![]),
+ Rvalue::Aggregate(Box::new(kind), IndexVec::new()),
))),
source_info,
});
@@ -286,7 +287,7 @@ impl<'tcx> TransformVisitor<'tcx> {
statements.push(Statement {
kind: StatementKind::Assign(Box::new((
Place::return_place(),
- Rvalue::Aggregate(Box::new(kind), vec![val]),
+ Rvalue::Aggregate(Box::new(kind), [val].into()),
))),
source_info,
});
@@ -297,7 +298,7 @@ impl<'tcx> TransformVisitor<'tcx> {
let self_place = Place::from(SELF_ARG);
let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index);
let mut projection = base.projection.to_vec();
- projection.push(ProjectionElem::Field(Field::new(idx), ty));
+ projection.push(ProjectionElem::Field(FieldIdx::new(idx), ty));
Place { local: base.local, projection: self.tcx.mk_place_elems(&projection) }
}
@@ -924,13 +925,19 @@ fn compute_layout<'tcx>(
debug!(?decl);
let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
+ // the information. This is alright, since `ignore_for_traits` is only relevant when
+ // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
+ // default.
match decl.local_info {
// Do not include raw pointers created from accessing `static` items, as those could
// well be re-created by another access to the same static.
- Some(box LocalInfo::StaticRef { is_thread_local, .. }) => !is_thread_local,
+ ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
+ !is_thread_local
+ }
// Fake borrows are only read by fake reads, so do not have any reality in
// post-analysis MIR.
- Some(box LocalInfo::FakeBorrow) => true,
+ ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
_ => false,
}
} else {
@@ -961,7 +968,7 @@ fn compute_layout<'tcx>(
// Build the generator variant field list.
// Create a map from local indices to generator struct indices.
- let mut variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>> =
+ let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>> =
iter::repeat(IndexVec::new()).take(RESERVED_VARIANTS).collect();
let mut remap = FxHashMap::default();
for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() {
@@ -1053,7 +1060,12 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let unwind = if block_data.is_cleanup {
Unwind::InCleanup
} else {
- Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
+ Unwind::To(match *unwind {
+ UnwindAction::Cleanup(tgt) => tgt,
+ UnwindAction::Continue => elaborator.patch.resume_block(),
+ UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
+ UnwindAction::Terminate => elaborator.patch.terminate_block(),
+ })
};
elaborate_drop(
&mut elaborator,
@@ -1140,7 +1152,7 @@ fn insert_panic_block<'tcx>(
expected: true,
msg: message,
target: assert_block,
- cleanup: None,
+ unwind: UnwindAction::Continue,
};
let source_info = SourceInfo::outermost(body.span);
@@ -1182,7 +1194,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These never unwind.
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@@ -1199,7 +1211,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These may unwind.
TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::InlineAsm { .. }
| TerminatorKind::Assert { .. } => return true,
@@ -1242,8 +1253,8 @@ fn create_generator_resume_function<'tcx>(
} else if !block.is_cleanup {
// Any terminators that *can* unwind but don't have an unwind target set are also
// pointed at our poisoning block (unless they're part of the cleanup path).
- if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
- *unwind = Some(poison_block);
+ if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() {
+ *unwind = UnwindAction::Cleanup(poison_block);
}
}
}
@@ -1288,8 +1299,11 @@ fn create_generator_resume_function<'tcx>(
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
let return_block = insert_term_block(body, TerminatorKind::Return);
- let term =
- TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None };
+ let term = TerminatorKind::Drop {
+ place: Place::from(SELF_ARG),
+ target: return_block,
+ unwind: UnwindAction::Continue,
+ };
let source_info = SourceInfo::outermost(body.span);
// Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -1381,10 +1395,9 @@ fn create_cases<'tcx>(
#[instrument(level = "debug", skip(tcx), ret)]
pub(crate) fn mir_generator_witnesses<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ def_id: LocalDefId,
) -> GeneratorLayout<'tcx> {
assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
- let def_id = def_id.expect_local();
let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
let body = body.borrow();
@@ -1543,6 +1556,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
body.arg_count = 2; // self, resume arg
body.spread_arg = None;
+ // The original arguments to the function are no longer arguments, mark them as such.
+ // Otherwise they'll conflict with our new arguments, which although they don't have
+ // argument_index set, will get emitted as unnamed arguments.
+ for var in &mut body.var_debug_info {
+ var.argument_index = None;
+ }
+
body.generator.as_mut().unwrap().yield_ty = None;
body.generator.as_mut().unwrap().generator_layout = Some(layout);
@@ -1648,6 +1668,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| StatementKind::StorageDead(_)
| StatementKind::Retag(..)
| StatementKind::AscribeUserType(..)
+ | StatementKind::PlaceMention(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
| StatementKind::ConstEvalCounter
@@ -1664,7 +1685,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
args,
destination,
target: Some(_),
- cleanup: _,
+ unwind: _,
from_hir_call: _,
fn_span: _,
} => {
@@ -1687,11 +1708,10 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Assert { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. }
@@ -1872,12 +1892,14 @@ fn check_must_not_suspend_def(
data: SuspendCheckData<'_>,
) -> bool {
if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) {
- let msg = format!(
- "{}`{}`{} held across a suspend point, but should not be",
- data.descr_pre,
- tcx.def_path_str(def_id),
- data.descr_post,
- );
+ let msg = rustc_errors::DelayDm(|| {
+ format!(
+ "{}`{}`{} held across a suspend point, but should not be",
+ data.descr_pre,
+ tcx.def_path_str(def_id),
+ data.descr_post,
+ )
+ });
tcx.struct_span_lint_hir(
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
hir_id,