diff options
Diffstat (limited to 'compiler/rustc_mir_transform/src')
21 files changed, 274 insertions, 139 deletions
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 5aed89139e2..4500bb7ff0f 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { for id in calls_to_terminate { let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Terminate; + *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } for id in cleanups_to_remove { diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index fb4705e0754..b814fbf32b1 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -53,8 +53,10 @@ impl AddCallGuards { kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. }, source_info, }) if pred_count[*destination] > 1 - && (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate) - || self == &AllCallEdges) => + && (matches!( + unwind, + UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) + ) || self == &AllCallEdges) => { // It's a critical edge, break it let call_guard = BasicBlockData { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 58e9786ec1a..0fce9cb19a8 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -57,8 +57,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Yield { .. } | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop - | TerminatorKind::Resume - | TerminatorKind::Terminate + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 7529ed8186b..a793b384d81 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -180,6 +180,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("calling functions isn't supported in ConstProp") } + fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &str) -> InterpResult<'tcx> { + throw_machine_stop_str!("panicking isn't supported in ConstProp") + } + fn find_mir_or_eval_fn( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index ac07c25763b..da8913d604b 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -678,8 +678,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { } // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Terminate + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index d1f2f0c76c8..3d442e5dca9 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -14,36 +14,76 @@ use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; use rustc_middle::mir::coverage::*; +use std::fmt::{self, Debug}; + +/// The coverage counter or counter expression associated with a particular +/// BCB node or BCB edge. +#[derive(Clone)] +pub(super) enum BcbCounter { + Counter { id: CounterId }, + Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand }, +} + +impl BcbCounter { + fn is_expression(&self) -> bool { + matches!(self, Self::Expression { .. }) + } + + pub(super) fn as_operand(&self) -> Operand { + match *self { + BcbCounter::Counter { id, .. } => Operand::Counter(id), + BcbCounter::Expression { id, .. } => Operand::Expression(id), + } + } +} + +impl Debug for BcbCounter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), + Self::Expression { id, lhs, op, rhs } => write!( + fmt, + "Expression({:?}) = {:?} {} {:?}", + id.index(), + lhs, + match op { + Op::Add => "+", + Op::Subtract => "-", + }, + rhs, + ), + } + } +} + /// Generates and stores coverage counter and coverage expression information /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { - function_source_hash: u64, next_counter_id: CounterId, next_expression_id: ExpressionId, /// Coverage counters/expressions that are associated with individual BCBs. - bcb_counters: IndexVec<BasicCoverageBlock, Option<CoverageKind>>, + bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>, /// Coverage counters/expressions that are associated with the control-flow /// edge between two BCBs. - bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), CoverageKind>, + bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, /// Tracks which BCBs have a counter associated with some incoming edge. /// Only used by debug assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>, /// Expression nodes that are not directly associated with any particular /// BCB/edge, but are needed as operands to more complex expressions. - /// These are always `CoverageKind::Expression`. - pub(super) intermediate_expressions: Vec<CoverageKind>, + /// These are always [`BcbCounter::Expression`]. + pub(super) intermediate_expressions: Vec<BcbCounter>, pub debug_counters: DebugCounters, } impl CoverageCounters { - pub(super) fn new(function_source_hash: u64, basic_coverage_blocks: &CoverageGraph) -> Self { + pub(super) fn new(basic_coverage_blocks: &CoverageGraph) -> Self { let num_bcbs = basic_coverage_blocks.num_nodes(); Self { - function_source_hash, next_counter_id: CounterId::START, next_expression_id: ExpressionId::START, @@ -57,12 +97,12 @@ impl CoverageCounters { } /// Activate the `DebugCounters` data structures, to provide additional debug formatting - /// features when formatting `CoverageKind` (counter) values. + /// features when formatting [`BcbCounter`] (counter) values. pub fn enable_debug(&mut self) { self.debug_counters.enable(); } - /// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or + /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or /// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s /// representing intermediate values. pub fn make_bcb_counters( @@ -73,14 +113,11 @@ impl CoverageCounters { MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans) } - fn make_counter<F>(&mut self, debug_block_label_fn: F) -> CoverageKind + fn make_counter<F>(&mut self, debug_block_label_fn: F) -> BcbCounter where F: Fn() -> Option<String>, { - let counter = CoverageKind::Counter { - function_source_hash: self.function_source_hash, - id: self.next_counter(), - }; + let counter = BcbCounter::Counter { id: self.next_counter() }; if self.debug_counters.is_enabled() { self.debug_counters.add_counter(&counter, (debug_block_label_fn)()); } @@ -93,19 +130,19 @@ impl CoverageCounters { op: Op, rhs: Operand, debug_block_label_fn: F, - ) -> CoverageKind + ) -> BcbCounter where F: Fn() -> Option<String>, { let id = self.next_expression(); - let expression = CoverageKind::Expression { id, lhs, op, rhs }; + let expression = BcbCounter::Expression { id, lhs, op, rhs }; if self.debug_counters.is_enabled() { self.debug_counters.add_counter(&expression, (debug_block_label_fn)()); } expression } - pub fn make_identity_counter(&mut self, counter_operand: Operand) -> CoverageKind { + pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter { let some_debug_block_label = if self.debug_counters.is_enabled() { self.debug_counters.some_block_label(counter_operand).cloned() } else { @@ -134,7 +171,7 @@ impl CoverageCounters { fn set_bcb_counter( &mut self, bcb: BasicCoverageBlock, - counter_kind: CoverageKind, + counter_kind: BcbCounter, ) -> Result<Operand, Error> { debug_assert!( // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also @@ -158,7 +195,7 @@ impl CoverageCounters { &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, - counter_kind: CoverageKind, + counter_kind: BcbCounter, ) -> Result<Operand, Error> { if level_enabled!(tracing::Level::DEBUG) { // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also @@ -183,17 +220,17 @@ impl CoverageCounters { } } - pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&CoverageKind> { + pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> { self.bcb_counters[bcb].as_ref() } - pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<CoverageKind> { + pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> { self.bcb_counters[bcb].take() } pub(super) fn drain_bcb_counters( &mut self, - ) -> impl Iterator<Item = (BasicCoverageBlock, CoverageKind)> + '_ { + ) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ { self.bcb_counters .iter_enumerated_mut() .filter_map(|(bcb, counter)| Some((bcb, counter.take()?))) @@ -201,7 +238,7 @@ impl CoverageCounters { pub(super) fn drain_bcb_edge_counters( &mut self, - ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), CoverageKind)> + '_ { + ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ { self.bcb_edge_counters.drain() } } @@ -653,7 +690,7 @@ impl<'a> MakeBcbCounters<'a> { self.branch_counter(branch).is_none() } - fn branch_counter(&self, branch: &BcbBranch) -> Option<&CoverageKind> { + fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> { let to_bcb = branch.target_bcb; if let Some(from_bcb) = branch.edge_from_bcb { self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)) @@ -675,7 +712,7 @@ impl<'a> MakeBcbCounters<'a> { } #[inline] - fn format_counter(&self, counter_kind: &CoverageKind) -> String { + fn format_counter(&self, counter_kind: &BcbCounter) -> String { self.coverage_counters.debug_counters.format_counter(counter_kind) } } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index d2c0c4ba069..af616c498fd 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -108,7 +108,7 @@ //! recursively, generating labels with nested operations, enclosed in parentheses //! (for example: `bcb2 + (bcb0 - bcb1)`). -use super::counters::CoverageCounters; +use super::counters::{BcbCounter, CoverageCounters}; use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use super::spans::CoverageSpan; @@ -199,9 +199,9 @@ impl DebugOptions { fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool { if let Some(val) = some_strval { - if vec!["yes", "y", "on", "true"].contains(&val) { + if ["yes", "y", "on", "true"].contains(&val) { true - } else if vec!["no", "n", "off", "false"].contains(&val) { + } else if ["no", "n", "off", "false"].contains(&val) { false } else { bug!( @@ -247,11 +247,11 @@ impl Default for ExpressionFormat { } } -/// If enabled, this struct maintains a map from `CoverageKind` IDs (as `Operand`) to -/// the `CoverageKind` data and optional label (normally, the counter's associated +/// If enabled, this struct maintains a map from `BcbCounter` IDs (as `Operand`) to +/// the `BcbCounter` data and optional label (normally, the counter's associated /// `BasicCoverageBlock` format string, if any). /// -/// Use `format_counter` to convert one of these `CoverageKind` counters to a debug output string, +/// Use `format_counter` to convert one of these `BcbCounter` counters to a debug output string, /// as directed by the `DebugOptions`. This allows the format of counter labels in logs and dump /// files (including the `CoverageGraph` graphviz file) to be changed at runtime, via environment /// variable. @@ -276,7 +276,7 @@ impl DebugCounters { self.some_counters.is_some() } - pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) { + pub fn add_counter(&mut self, counter_kind: &BcbCounter, some_block_label: Option<String>) { if let Some(counters) = &mut self.some_counters { let id = counter_kind.as_operand(); counters @@ -291,21 +291,20 @@ impl DebugCounters { }) } - pub fn format_counter(&self, counter_kind: &CoverageKind) -> String { + pub fn format_counter(&self, counter_kind: &BcbCounter) -> String { match *counter_kind { - CoverageKind::Counter { .. } => { + BcbCounter::Counter { .. } => { format!("Counter({})", self.format_counter_kind(counter_kind)) } - CoverageKind::Expression { .. } => { + BcbCounter::Expression { .. } => { format!("Expression({})", self.format_counter_kind(counter_kind)) } - CoverageKind::Unreachable { .. } => "Unreachable".to_owned(), } } - fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String { + fn format_counter_kind(&self, counter_kind: &BcbCounter) -> String { let counter_format = &debug_options().counter_format; - if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind { + if let BcbCounter::Expression { id, lhs, op, rhs } = *counter_kind { if counter_format.operation { return format!( "{}{} {} {}", @@ -346,7 +345,7 @@ impl DebugCounters { } if let Some(counters) = &self.some_counters { if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) { - if let CoverageKind::Expression { .. } = counter_kind { + if let BcbCounter::Expression { .. } = counter_kind { if let Some(label) = some_block_label && debug_options().counter_format.block { return format!( "{}:({})", @@ -366,12 +365,12 @@ impl DebugCounters { /// A non-public support class to `DebugCounters`. #[derive(Debug)] struct DebugCounter { - counter_kind: CoverageKind, + counter_kind: BcbCounter, some_block_label: Option<String>, } impl DebugCounter { - fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self { + fn new(counter_kind: BcbCounter, some_block_label: Option<String>) -> Self { Self { counter_kind, some_block_label } } } @@ -380,9 +379,9 @@ impl DebugCounter { /// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes. pub(super) struct GraphvizData { some_bcb_to_coverage_spans_with_counters: - Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, CoverageKind)>>>, - some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<CoverageKind>>>, - some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), CoverageKind>>, + Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, BcbCounter)>>>, + some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<BcbCounter>>>, + some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), BcbCounter>>, } impl GraphvizData { @@ -409,7 +408,7 @@ impl GraphvizData { &mut self, bcb: BasicCoverageBlock, coverage_span: &CoverageSpan, - counter_kind: &CoverageKind, + counter_kind: &BcbCounter, ) { if let Some(bcb_to_coverage_spans_with_counters) = self.some_bcb_to_coverage_spans_with_counters.as_mut() @@ -424,7 +423,7 @@ impl GraphvizData { pub fn get_bcb_coverage_spans_with_counters( &self, bcb: BasicCoverageBlock, - ) -> Option<&[(CoverageSpan, CoverageKind)]> { + ) -> Option<&[(CoverageSpan, BcbCounter)]> { if let Some(bcb_to_coverage_spans_with_counters) = self.some_bcb_to_coverage_spans_with_counters.as_ref() { @@ -437,7 +436,7 @@ impl GraphvizData { pub fn add_bcb_dependency_counter( &mut self, bcb: BasicCoverageBlock, - counter_kind: &CoverageKind, + counter_kind: &BcbCounter, ) { if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() { bcb_to_dependency_counters @@ -447,7 +446,7 @@ impl GraphvizData { } } - pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[CoverageKind]> { + pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[BcbCounter]> { if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() { bcb_to_dependency_counters.get(&bcb).map(Deref::deref) } else { @@ -459,7 +458,7 @@ impl GraphvizData { &mut self, from_bcb: BasicCoverageBlock, to_bb: BasicBlock, - counter_kind: &CoverageKind, + counter_kind: &BcbCounter, ) { if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() { edge_to_counter @@ -472,7 +471,7 @@ impl GraphvizData { &self, from_bcb: BasicCoverageBlock, to_bb: BasicBlock, - ) -> Option<&CoverageKind> { + ) -> Option<&BcbCounter> { if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() { edge_to_counter.get(&(from_bcb, to_bb)) } else { @@ -488,7 +487,7 @@ impl GraphvizData { pub(super) struct UsedExpressions { some_used_expression_operands: Option<FxHashMap<Operand, Vec<ExpressionId>>>, some_unused_expressions: - Option<Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)>>, + Option<Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)>>, } impl UsedExpressions { @@ -506,16 +505,16 @@ impl UsedExpressions { self.some_used_expression_operands.is_some() } - pub fn add_expression_operands(&mut self, expression: &CoverageKind) { + pub fn add_expression_operands(&mut self, expression: &BcbCounter) { if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() { - if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression { + if let BcbCounter::Expression { id, lhs, rhs, .. } = *expression { used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id); used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id); } } } - pub fn expression_is_used(&self, expression: &CoverageKind) -> bool { + pub fn expression_is_used(&self, expression: &BcbCounter) -> bool { if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() { used_expression_operands.contains_key(&expression.as_operand()) } else { @@ -525,7 +524,7 @@ impl UsedExpressions { pub fn add_unused_expression_if_not_found( &mut self, - expression: &CoverageKind, + expression: &BcbCounter, edge_from_bcb: Option<BasicCoverageBlock>, target_bcb: BasicCoverageBlock, ) { @@ -540,11 +539,11 @@ impl UsedExpressions { } } - /// Return the list of unused counters (if any) as a tuple with the counter (`CoverageKind`), + /// Return the list of unused counters (if any) as a tuple with the counter (`BcbCounter`), /// optional `from_bcb` (if it was an edge counter), and `target_bcb`. pub fn get_unused_expressions( &self, - ) -> Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)> { + ) -> Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)> { if let Some(unused_expressions) = self.some_unused_expressions.as_ref() { unused_expressions.clone() } else { @@ -560,7 +559,7 @@ impl UsedExpressions { bcb_counters_without_direct_coverage_spans: &[( Option<BasicCoverageBlock>, BasicCoverageBlock, - CoverageKind, + BcbCounter, )], ) { if self.is_enabled() { @@ -662,7 +661,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>( basic_coverage_blocks: &CoverageGraph, coverage_counters: &CoverageCounters, graphviz_data: &GraphvizData, - intermediate_expressions: &[CoverageKind], + intermediate_expressions: &[BcbCounter], debug_used_expressions: &UsedExpressions, ) { let debug_counters = &coverage_counters.debug_counters; @@ -743,9 +742,9 @@ fn bcb_to_string_sections<'tcx>( coverage_counters: &CoverageCounters, bcb: BasicCoverageBlock, bcb_data: &BasicCoverageBlockData, - some_coverage_spans_with_counters: Option<&[(CoverageSpan, CoverageKind)]>, - some_dependency_counters: Option<&[CoverageKind]>, - some_intermediate_expressions: Option<&[CoverageKind]>, + some_coverage_spans_with_counters: Option<&[(CoverageSpan, BcbCounter)]>, + some_dependency_counters: Option<&[BcbCounter]>, + some_intermediate_expressions: Option<&[BcbCounter]>, ) -> Vec<String> { let debug_counters = &coverage_counters.debug_counters; diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 59b01ffec0f..60461691e7f 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -116,7 +116,7 @@ impl CoverageGraph { match term.kind { TerminatorKind::Return { .. } - | TerminatorKind::Terminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the @@ -146,7 +146,7 @@ impl CoverageGraph { // is as intended. (See Issue #78544 for a possible future option to support // coverage in test programs that panic.) TerminatorKind::Goto { .. } - | TerminatorKind::Resume + | TerminatorKind::UnwindResume | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } | TerminatorKind::Call { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index e08b6d6f6e8..8c9eae508b4 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -8,9 +8,9 @@ mod spans; #[cfg(test)] mod tests; -use counters::CoverageCounters; -use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; -use spans::{CoverageSpan, CoverageSpans}; +use self::counters::{BcbCounter, CoverageCounters}; +use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; +use self::spans::{CoverageSpan, CoverageSpans}; use crate::MirPass; @@ -106,6 +106,7 @@ struct Instrumentor<'a, 'tcx> { source_file: Lrc<SourceFile>, fn_sig_span: Span, body_span: Span, + function_source_hash: u64, basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, } @@ -137,7 +138,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let function_source_hash = hash_mir_source(tcx, hir_body); let basic_coverage_blocks = CoverageGraph::from_mir(mir_body); - let coverage_counters = CoverageCounters::new(function_source_hash, &basic_coverage_blocks); + let coverage_counters = CoverageCounters::new(&basic_coverage_blocks); Self { pass_name, @@ -146,6 +147,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { source_file, fn_sig_span, body_span, + function_source_hash, basic_coverage_blocks, coverage_counters, } @@ -270,8 +272,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { //////////////////////////////////////////////////// // Finally, inject the intermediate expressions collected along the way. - for intermediate_expression in self.coverage_counters.intermediate_expressions.drain(..) { - inject_intermediate_expression(self.mir_body, intermediate_expression); + for intermediate_expression in &self.coverage_counters.intermediate_expressions { + inject_intermediate_expression( + self.mir_body, + self.make_mir_coverage_kind(intermediate_expression), + ); } } @@ -309,19 +314,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { }; graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind); - debug!( - "Calling make_code_region(file_name={}, source_file={:?}, span={}, body_span={})", - file_name, - self.source_file, - source_map.span_to_diagnostic_string(span), - source_map.span_to_diagnostic_string(body_span) - ); + let code_region = + make_code_region(source_map, file_name, &self.source_file, span, body_span); inject_statement( self.mir_body, - counter_kind, + self.make_mir_coverage_kind(&counter_kind), self.bcb_leader_bb(bcb), - Some(make_code_region(source_map, file_name, &self.source_file, span, body_span)), + Some(code_region), ); } } @@ -367,7 +367,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); match counter_kind { - CoverageKind::Counter { .. } => { + BcbCounter::Counter { .. } => { let inject_to_bb = if let Some(from_bcb) = edge_from_bcb { // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the @@ -400,12 +400,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { target_bb }; - inject_statement(self.mir_body, counter_kind, inject_to_bb, None); + inject_statement( + self.mir_body, + self.make_mir_coverage_kind(&counter_kind), + inject_to_bb, + None, + ); } - CoverageKind::Expression { .. } => { - inject_intermediate_expression(self.mir_body, counter_kind) - } - _ => bug!("CoverageKind should be a counter"), + BcbCounter::Expression { .. } => inject_intermediate_expression( + self.mir_body, + self.make_mir_coverage_kind(&counter_kind), + ), } } } @@ -426,9 +431,20 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { } #[inline] - fn format_counter(&self, counter_kind: &CoverageKind) -> String { + fn format_counter(&self, counter_kind: &BcbCounter) -> String { self.coverage_counters.debug_counters.format_counter(counter_kind) } + + fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { + match *counter_kind { + BcbCounter::Counter { id } => { + CoverageKind::Counter { function_source_hash: self.function_source_hash, id } + } + BcbCounter::Expression { id, lhs, op, rhs } => { + CoverageKind::Expression { id, lhs, op, rhs } + } + } + } } fn inject_edge_counter_basic_block( @@ -498,6 +514,14 @@ fn make_code_region( span: Span, body_span: Span, ) -> CodeRegion { + debug!( + "Called make_code_region(file_name={}, source_file={:?}, span={}, body_span={})", + file_name, + source_file, + source_map.span_to_diagnostic_string(span), + source_map.span_to_diagnostic_string(body_span) + ); + let (start_line, mut start_col) = source_file.lookup_file_pos(span.lo()); let (end_line, end_col) = if span.hi() == span.lo() { let (end_line, mut end_col) = (start_line, start_col); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index deebf5345ba..717763a94a0 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -867,8 +867,8 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp } // Retain spans from all other terminators - TerminatorKind::Resume - | TerminatorKind::Terminate + TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index d797a6057a7..4a066ed3abd 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -34,7 +34,6 @@ use itertools::Itertools; use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::graph::WithSuccessors; use rustc_index::{Idx, IndexVec}; -use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::*; use rustc_middle::ty; use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP}; @@ -675,8 +674,8 @@ fn test_make_bcb_counters() { )); } } - let mut coverage_counters = counters::CoverageCounters::new(0, &basic_coverage_blocks); - let () = coverage_counters + let mut coverage_counters = counters::CoverageCounters::new(&basic_coverage_blocks); + coverage_counters .make_bcb_counters(&mut basic_coverage_blocks, &coverage_spans) .expect("should be Ok"); assert_eq!(coverage_counters.intermediate_expressions.len(), 0); @@ -685,7 +684,7 @@ fn test_make_bcb_counters() { assert_eq!( 0, // bcb1 has a `Counter` with id = 0 match coverage_counters.bcb_counter(bcb1).expect("should have a counter") { - CoverageKind::Counter { id, .. } => id, + counters::BcbCounter::Counter { id, .. } => id, _ => panic!("expected a Counter"), } .as_u32() @@ -695,7 +694,7 @@ fn test_make_bcb_counters() { assert_eq!( 1, // bcb2 has a `Counter` with id = 1 match coverage_counters.bcb_counter(bcb2).expect("should have a counter") { - CoverageKind::Counter { id, .. } => id, + counters::BcbCounter::Counter { id, .. } => id, _ => panic!("expected a Counter"), } .as_u32() diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 8f4dc9f69e9..3a1ef3e7d64 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -541,6 +541,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm unimplemented!() } + fn panic_nounwind( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _msg: &str, + ) -> interpret::InterpResult<'tcx> { + unimplemented!() + } + fn call_intrinsic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3f988930b5e..ef14105041b 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -12,6 +12,7 @@ //! will still not cause any further changes. //! +use crate::util::is_within_packed; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -49,6 +50,11 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS && !place.is_indirect() && !borrowed.contains(place.local) && !state.contains(place.local) + // If `place` is a projection of a disaligned field in a packed ADT, + // the move may be codegened as a pointer to that field. + // Using that disaligned pointer may trigger UB in the callee, + // so do nothing. + && is_within_packed(tcx, body, place).is_none() { call_operands_to_move.push((bb, index)); } diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 60ca3dfb2da..79645310a39 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -203,7 +203,12 @@ pub fn deduced_param_attrs<'tcx>( body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { read_only: !deduce_read_only.mutable_args.contains(arg_index) - && local_decl.ty.is_freeze(tcx, param_env), + // We must normalize here to reveal opaques and normalize + // their substs, otherwise we'll see exponential blow-up in + // compile times: #113372 + && tcx + .normalize_erasing_regions(param_env, local_decl.ty) + .is_freeze(tcx, param_env), }, ), ); diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index b73b72c3192..d9a132e5cf1 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -647,8 +647,8 @@ impl WriteInfo { } } TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Terminate + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable { .. } => (), TerminatorKind::Drop { .. } => { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index b6b1ae6d3c3..78d7ffb3698 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { UnwindAction::Unreachable => { Unwind::To(self.patch.unreachable_cleanup_block()) } - UnwindAction::Terminate => { - Unwind::To(self.patch.terminate_block()) + UnwindAction::Terminate(reason) => { + debug_assert_ne!( + reason, + UnwindTerminateReason::InCleanup, + "we are not in a cleanup block, InCleanup reason should be impossible" + ); + Unwind::To(self.patch.terminate_block(reason)) } } }; @@ -470,7 +475,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // drop elaboration should handle that by itself continue; } - TerminatorKind::Resume => { + TerminatorKind::UnwindResume => { // It is possible for `Resume` to be patched // (in particular it can be patched to be replaced with // a Goto; see `MirPatch::new`). @@ -496,7 +501,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { if let TerminatorKind::Call { destination, target: Some(_), - unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate, + unwind: + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_), .. } = data.terminator().kind { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 797a1a86846..1e7161189c3 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -50,8 +50,10 @@ //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. +use crate::abort_unwinding_calls; use crate::deref_separator::deref_finder; use crate::errors; +use crate::pass_manager as pm; use crate::simplify; use crate::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -64,6 +66,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::dump_mir; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::InstanceDef; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_middle::ty::{GeneratorArgs, GenericArgsRef}; use rustc_mir_dataflow::impls::{ @@ -1088,7 +1091,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { UnwindAction::Cleanup(tgt) => tgt, UnwindAction::Continue => elaborator.patch.resume_block(), UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(), - UnwindAction::Terminate => elaborator.patch.terminate_block(), + UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason), }) }; elaborate_drop( @@ -1147,7 +1150,25 @@ fn create_generator_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(tcx, &mut body); + // Update the body's def to become the drop glue. + // This needs to be updated before the AbortUnwindingCalls pass. + let gen_instance = body.source.instance; + let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None); + let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(gen_ty)); + body.source.instance = drop_instance; + + pm::run_passes_no_validate( + tcx, + &mut body, + &[&abort_unwinding_calls::AbortUnwindingCalls], + None, + ); + + // Temporary change MirSource to generator's instance so that dump_mir produces more sensible + // filename. + body.source.instance = gen_instance; dump_mir(tcx, false, "generator_drop", &0, &body, |_, _| Ok(())); + body.source.instance = drop_instance; body } @@ -1218,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These never unwind. TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Terminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -1227,7 +1248,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // Resume will *continue* unwinding, but if there's no other unwinding terminator it // will never be reached. - TerminatorKind::Resume => {} + TerminatorKind::UnwindResume => {} TerminatorKind::Yield { .. } => { unreachable!("`can_unwind` called before generator transform") @@ -1258,14 +1279,14 @@ fn create_generator_resume_function<'tcx>( let source_info = SourceInfo::outermost(body.span); let poison_block = body.basic_blocks_mut().push(BasicBlockData { statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], - terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), + terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }), is_cleanup: true, }); for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() { let source_info = block.terminator().source_info; - if let TerminatorKind::Resume = block.terminator().kind { + if let TerminatorKind::UnwindResume = block.terminator().kind { // An existing `Resume` terminator is redirected to jump to our dedicated // "poisoning block" above. if idx != poison_block { @@ -1317,6 +1338,8 @@ fn create_generator_resume_function<'tcx>( // unrelated code from the drop part of the function simplify::remove_dead_blocks(tcx, body); + pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); + dump_mir(tcx, false, "generator_resume", &0, body, |_, _| Ok(())); } @@ -1735,8 +1758,8 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { TerminatorKind::Call { .. } | TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Resume - | TerminatorKind::Terminate + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index fc9e18378d5..9551c7a2a8d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -839,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { self.cost += LANDINGPAD_PENALTY; } } - TerminatorKind::Resume => self.cost += RESUME_PENALTY, + TerminatorKind::UnwindResume => self.cost += RESUME_PENALTY, TerminatorKind::InlineAsm { unwind, .. } => { self.cost += INSTR_COST; if let UnwindAction::Cleanup(_) = unwind { @@ -906,12 +906,12 @@ impl Integrator<'_, '_> { UnwindAction::Cleanup(_) | UnwindAction::Continue => { bug!("cleanup on cleanup block"); } - UnwindAction::Unreachable | UnwindAction::Terminate => return unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => return unwind, } } match unwind { - UnwindAction::Unreachable | UnwindAction::Terminate => unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => unwind, UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)), // Add an unwind edge to the original call's cleanup block UnwindAction::Continue => self.cleanup_block, @@ -1017,15 +1017,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { TerminatorKind::Unreachable } } - TerminatorKind::Resume => { + TerminatorKind::UnwindResume => { terminator.kind = match self.cleanup_block { UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt }, - UnwindAction::Continue => TerminatorKind::Resume, + UnwindAction::Continue => TerminatorKind::UnwindResume, UnwindAction::Unreachable => TerminatorKind::Unreachable, - UnwindAction::Terminate => TerminatorKind::Terminate, + UnwindAction::Terminate(reason) => TerminatorKind::UnwindTerminate(reason), }; } - TerminatorKind::Terminate => {} + TerminatorKind::UnwindTerminate(_) => {} TerminatorKind::Unreachable => {} TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => { *real_target = self.map_block(*real_target); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 4941c9edce3..8c48a667786 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -6,8 +6,8 @@ use rustc_middle::ty::TyCtxt; use rustc_target::spec::PanicStrategy; /// A pass that removes noop landing pads and replaces jumps to them with -/// `None`. This is important because otherwise LLVM generates terrible -/// code for these. +/// `UnwindAction::Continue`. This is important because otherwise LLVM generates +/// terrible code for these. pub struct RemoveNoopLandingPads; impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { @@ -63,7 +63,7 @@ impl RemoveNoopLandingPads { let terminator = body[bb].terminator(); match terminator.kind { TerminatorKind::Goto { .. } - | TerminatorKind::Resume + | TerminatorKind::UnwindResume | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { @@ -72,7 +72,7 @@ impl RemoveNoopLandingPads { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::Return - | TerminatorKind::Terminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } @@ -84,7 +84,17 @@ impl RemoveNoopLandingPads { fn remove_nop_landing_pads(&self, body: &mut Body<'_>) { debug!("body: {:#?}", body); - // make sure there's a resume block + // Skip the pass if there are no blocks with a resume terminator. + let has_resume = body + .basic_blocks + .iter_enumerated() + .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume)); + if !has_resume { + debug!("remove_noop_landing_pads: no resume block in MIR"); + return; + } + + // make sure there's a resume block without any statements let resume_block = { let mut patch = MirPatch::new(body); let resume_block = patch.resume_block(); diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 1d8e54cdca0..e1e4acccccd 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -108,13 +108,13 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { } // The following terminators are not allowed - TerminatorKind::Resume + TerminatorKind::UnwindResume | TerminatorKind::Drop { .. } | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield { .. } - | TerminatorKind::Terminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::InlineAsm { .. } @@ -165,8 +165,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { }); } - TerminatorKind::Resume - | TerminatorKind::Terminate + TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 5e8ba4f544c..e1000d96932 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -71,8 +71,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' // of this function. Is this intentional? if let Some(ty::Generator(gen_def_id, args, _)) = ty.map(Ty::kind) { let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap(); - let body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); + let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); + + // Run empty passes to mark phase change and perform validation. + pm::run_passes( + tcx, + &mut body, + &[], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), + ); + return body; } @@ -90,7 +99,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - pm::run_passes( + // We don't validate MIR here because the shims may generate code that's + // only valid in a reveal-all param-env. However, since we do initial + // validation with the MirBuilt phase, which uses a user-facing param-env. + // This causes validation errors when TAITs are involved. + pm::run_passes_no_validate( tcx, &mut result, &[ @@ -557,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { TerminatorKind::Drop { place: dest_field, target: unwind, - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); unwind = next_unwind; } @@ -574,7 +587,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { I: IntoIterator<Item = Ty<'tcx>>, { self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false); - let unwind = self.block(vec![], TerminatorKind::Resume, true); + let unwind = self.block(vec![], TerminatorKind::UnwindResume, true); let target = self.block(vec![], TerminatorKind::Return, false); let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys); @@ -588,7 +601,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { args: GeneratorArgs<'tcx>, ) { self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false); - let unwind = self.block(vec![], TerminatorKind::Resume, true); + let unwind = self.block(vec![], TerminatorKind::UnwindResume, true); // This will get overwritten with a switch once we know the target blocks let switch = self.block(vec![], TerminatorKind::Unreachable, false); let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys()); @@ -838,14 +851,14 @@ fn build_call_shim<'tcx>( TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); // BB #4 - resume - block(&mut blocks, vec![], TerminatorKind::Resume, true); + block(&mut blocks, vec![], TerminatorKind::UnwindResume, true); } let mut body = |
