Skip to content

Commit 1d315cf

Browse files
committed
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.
1 parent 7c0c4cd commit 1d315cf

File tree

19 files changed

+94
-10
lines changed

19 files changed

+94
-10
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ for mir::StatementKind<'tcx> {
226226
mir::StatementKind::StorageDead(ref lvalue) => {
227227
lvalue.hash_stable(hcx, hasher);
228228
}
229+
mir::StatementKind::EndRegion(ref extents) => {
230+
extents.hash_stable(hcx, hasher);
231+
}
229232
mir::StatementKind::Nop => {}
230233
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
231234
asm.hash_stable(hcx, hasher);

src/librustc/mir/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use graphviz::IntoCow;
1414
use middle::const_val::ConstVal;
15+
use middle::region::CodeExtent;
1516
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
1617
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
1718
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
@@ -804,6 +805,10 @@ pub enum StatementKind<'tcx> {
804805
inputs: Vec<Operand<'tcx>>
805806
},
806807

808+
/// Mark one terminating point of an extent (i.e. static region).
809+
/// (The starting point(s) arise implicitly from borrows.)
810+
EndRegion(CodeExtent),
811+
807812
/// No-op. Useful for deleting instructions without affecting statement indices.
808813
Nop,
809814
}
@@ -813,6 +818,8 @@ impl<'tcx> Debug for Statement<'tcx> {
813818
use self::StatementKind::*;
814819
match self.kind {
815820
Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
821+
// (reuse lifetime rendering policy from ppaux.)
822+
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
816823
StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv),
817824
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
818825
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
@@ -1472,6 +1479,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
14721479
outputs: outputs.fold_with(folder),
14731480
inputs: inputs.fold_with(folder)
14741481
},
1482+
1483+
// Note for future: If we want to expose the extents
1484+
// during the fold, we need to either generalize EndRegion
1485+
// to carry `[ty::Region]`, or extend the `TypeFolder`
1486+
// trait with a `fn fold_extent`.
1487+
EndRegion(ref extent) => EndRegion(extent.clone()),
1488+
14751489
Nop => Nop,
14761490
};
14771491
Statement {
@@ -1490,6 +1504,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
14901504
StorageDead(ref lvalue) => lvalue.visit_with(visitor),
14911505
InlineAsm { ref outputs, ref inputs, .. } =>
14921506
outputs.visit_with(visitor) || inputs.visit_with(visitor),
1507+
1508+
// Note for future: If we want to expose the extents
1509+
// during the visit, we need to either generalize EndRegion
1510+
// to carry `[ty::Region]`, or extend the `TypeVisitor`
1511+
// trait with a `fn visit_extent`.
1512+
EndRegion(ref _extent) => false,
1513+
14931514
Nop => false,
14941515
}
14951516
}

src/librustc/mir/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ macro_rules! make_mir_visitor {
325325
ref $($mutability)* rvalue) => {
326326
self.visit_assign(block, lvalue, rvalue, location);
327327
}
328+
StatementKind::EndRegion(_) => {}
328329
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
329330
self.visit_lvalue(lvalue, LvalueContext::Store, location);
330331
}

src/librustc_borrowck/borrowck/mir/dataflow/impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
474474
mir::StatementKind::StorageLive(_) |
475475
mir::StatementKind::StorageDead(_) |
476476
mir::StatementKind::InlineAsm { .. } |
477+
mir::StatementKind::EndRegion(_) |
477478
mir::StatementKind::Nop => {}
478479
}
479480
}

src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
105105
mir::StatementKind::StorageLive(_) |
106106
mir::StatementKind::StorageDead(_) |
107107
mir::StatementKind::InlineAsm { .. } |
108+
mir::StatementKind::EndRegion(_) |
108109
mir::StatementKind::Nop => continue,
109110
mir::StatementKind::SetDiscriminant{ .. } =>
110111
span_bug!(stmt.source_info.span,

src/librustc_borrowck/borrowck/mir/elaborate_drops.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
585585
// drop elaboration should handle that by itself
586586
continue
587587
}
588+
TerminatorKind::Resume => {
589+
// We can replace resumes with gotos
590+
// jumping to a canonical resume.
591+
continue
592+
}
588593
TerminatorKind::DropAndReplace { .. } => {
589594
// this contains the move of the source and
590595
// the initialization of the destination. We

src/librustc_borrowck/borrowck/mir/gather_moves.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
413413
"SetDiscriminant should not exist during borrowck");
414414
}
415415
StatementKind::InlineAsm { .. } |
416+
StatementKind::EndRegion(_) |
416417
StatementKind::Nop => {}
417418
}
418419
}

src/librustc_borrowck/borrowck/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
394394
mir::StatementKind::StorageLive(_) |
395395
mir::StatementKind::StorageDead(_) |
396396
mir::StatementKind::InlineAsm { .. } |
397+
mir::StatementKind::EndRegion(_) |
397398
mir::StatementKind::Nop => {}
398399
},
399400
None => {

src/librustc_mir/build/block.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
7171
let outer_visibility_scope = this.visibility_scope;
7272
let source_info = this.source_info(span);
7373
for stmt in stmts {
74-
let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt);
74+
let Stmt { span, kind, opt_destruction_extent } = this.hir.mirror(stmt);
7575
match kind {
7676
StmtKind::Expr { scope, expr } => {
7777
unpack!(block = this.in_opt_scope(
@@ -122,7 +122,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
122122
if let Some(expr) = expr {
123123
unpack!(block = this.into(destination, block, expr));
124124
} else {
125-
let source_info = this.source_info(span);
126125
this.cfg.push_assign_unit(block, source_info, destination);
127126
}
128127
// Finally, we pop all the let scopes before exiting out from the scope of block

src/librustc_mir/build/cfg.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//! Routines for manipulating the control-flow graph.
1515
1616
use build::CFG;
17+
use rustc::middle::region::CodeExtent;
1718
use rustc::mir::*;
1819

1920
impl<'tcx> CFG<'tcx> {
@@ -43,6 +44,16 @@ impl<'tcx> CFG<'tcx> {
4344
self.block_data_mut(block).statements.push(statement);
4445
}
4546

47+
pub fn push_end_region(&mut self,
48+
block: BasicBlock,
49+
source_info: SourceInfo,
50+
extent: CodeExtent) {
51+
self.push(block, Statement {
52+
source_info: source_info,
53+
kind: StatementKind::EndRegion(extent),
54+
});
55+
}
56+
4657
pub fn push_assign(&mut self,
4758
block: BasicBlock,
4859
source_info: SourceInfo,

0 commit comments

Comments
 (0)