Add EndRegion statement kind to MIR.
* Emit `EndRegion` for every code-extent for which we observe a borrow. To do this, we needed to thread source info back through to `fn in_scope`, which makes this commit a bit more painful than one might have expected. * There is `end_region` emission in `Builder::pop_scope` and in `Builder::exit_scope`; the first handles falling out of a scope normally, the second handles e.g. `break`. * Remove `EndRegion` statements during the erase_regions mir transformation. * Preallocate the terminator block, and throw an `Unreachable` marker on it from the outset. Then overwrite that Terminator as necessary on demand. * Instead of marking the scope as needs_cleanup after seeing a borrow, just treat every scope in the chain as being part of the diverge_block (after any *one* of them has separately signalled that it needs cleanup, e.g. due to having a destructor to run). * Allow for resume terminators to be patched when looking up drop flags. (In particular, `MirPatch::new` has an explicit code path, presumably previously unreachable, that patches up such resume terminators.) * Make `Scope` implement `Debug` trait. * Expanded a stray comment: we do not emit StorageDead on diverging paths, but that end behavior might not be desirable.
This commit is contained in:
parent
7c0c4cde80
commit
1d315cf7da
19 changed files with 94 additions and 10 deletions
|
|
@ -226,6 +226,9 @@ for mir::StatementKind<'tcx> {
|
|||
mir::StatementKind::StorageDead(ref lvalue) => {
|
||||
lvalue.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::EndRegion(ref extents) => {
|
||||
extents.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::Nop => {}
|
||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
asm.hash_stable(hcx, hasher);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
use graphviz::IntoCow;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::region::CodeExtent;
|
||||
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
|
||||
|
|
@ -804,6 +805,10 @@ pub enum StatementKind<'tcx> {
|
|||
inputs: Vec<Operand<'tcx>>
|
||||
},
|
||||
|
||||
/// Mark one terminating point of an extent (i.e. static region).
|
||||
/// (The starting point(s) arise implicitly from borrows.)
|
||||
EndRegion(CodeExtent),
|
||||
|
||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||
Nop,
|
||||
}
|
||||
|
|
@ -813,6 +818,8 @@ impl<'tcx> Debug for Statement<'tcx> {
|
|||
use self::StatementKind::*;
|
||||
match self.kind {
|
||||
Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
|
||||
// (reuse lifetime rendering policy from ppaux.)
|
||||
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
|
||||
StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv),
|
||||
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
|
||||
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
|
||||
|
|
@ -1472,6 +1479,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
|||
outputs: outputs.fold_with(folder),
|
||||
inputs: inputs.fold_with(folder)
|
||||
},
|
||||
|
||||
// Note for future: If we want to expose the extents
|
||||
// during the fold, we need to either generalize EndRegion
|
||||
// to carry `[ty::Region]`, or extend the `TypeFolder`
|
||||
// trait with a `fn fold_extent`.
|
||||
EndRegion(ref extent) => EndRegion(extent.clone()),
|
||||
|
||||
Nop => Nop,
|
||||
};
|
||||
Statement {
|
||||
|
|
@ -1490,6 +1504,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
|
|||
StorageDead(ref lvalue) => lvalue.visit_with(visitor),
|
||||
InlineAsm { ref outputs, ref inputs, .. } =>
|
||||
outputs.visit_with(visitor) || inputs.visit_with(visitor),
|
||||
|
||||
// Note for future: If we want to expose the extents
|
||||
// during the visit, we need to either generalize EndRegion
|
||||
// to carry `[ty::Region]`, or extend the `TypeVisitor`
|
||||
// trait with a `fn visit_extent`.
|
||||
EndRegion(ref _extent) => false,
|
||||
|
||||
Nop => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ macro_rules! make_mir_visitor {
|
|||
ref $($mutability)* rvalue) => {
|
||||
self.visit_assign(block, lvalue, rvalue, location);
|
||||
}
|
||||
StatementKind::EndRegion(_) => {}
|
||||
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
|
||||
self.visit_lvalue(lvalue, LvalueContext::Store, location);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue