Skip to content

Commit e1ebdee

Browse files
committed
Revert "Defer creating drop trees in MIR lowering until leaving that scope"
This reverts commit 6119885.
1 parent 7cde4ab commit e1ebdee

File tree

8 files changed

+735
-769
lines changed

8 files changed

+735
-769
lines changed

src/librustc_mir/util/graphviz.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,12 @@ where
9797
write!(w, r#"<table border="0" cellborder="1" cellspacing="0">"#)?;
9898

9999
// Basic block number at the top.
100-
let (blk, color) = if data.is_cleanup {
101-
(format!("{} (cleanup)", block.index()), "lightblue")
102-
} else {
103-
(format!("{}", block.index()), "gray")
104-
};
105100
write!(
106101
w,
107-
r#"<tr><td bgcolor="{color}" align="center" colspan="{colspan}">{blk}</td></tr>"#,
102+
r#"<tr><td {attrs} colspan="{colspan}">{blk}</td></tr>"#,
103+
attrs = r#"bgcolor="gray" align="center""#,
108104
colspan = num_cols,
109-
blk = blk,
110-
color = color
105+
blk = block.index()
111106
)?;
112107

113108
init(w)?;

src/librustc_mir_build/build/block.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2828
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
2929
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
3030
if targeted_by_break {
31-
this.in_breakable_scope(None, destination, span, |this| {
32-
Some(this.ast_block_stmts(
33-
destination,
34-
block,
35-
span,
36-
stmts,
37-
expr,
38-
safety_mode,
39-
))
40-
})
31+
// This is a `break`-able block
32+
let exit_block = this.cfg.start_new_block();
33+
let block_exit =
34+
this.in_breakable_scope(None, exit_block, destination, |this| {
35+
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
36+
});
37+
this.cfg.goto(unpack!(block_exit), source_info, exit_block);
38+
exit_block.unit()
4139
} else {
4240
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
4341
}

src/librustc_mir_build/build/expr/into.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -135,30 +135,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
135135
// body, even when the exact code in the body cannot unwind
136136

137137
let loop_block = this.cfg.start_new_block();
138+
let exit_block = this.cfg.start_new_block();
138139

139140
// Start the loop.
140141
this.cfg.goto(block, source_info, loop_block);
141142

142-
this.in_breakable_scope(Some(loop_block), destination, expr_span, move |this| {
143+
this.in_breakable_scope(Some(loop_block), exit_block, destination, move |this| {
143144
// conduct the test, if necessary
144145
let body_block = this.cfg.start_new_block();
146+
let diverge_cleanup = this.diverge_cleanup();
145147
this.cfg.terminate(
146148
loop_block,
147149
source_info,
148-
TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
150+
TerminatorKind::FalseUnwind {
151+
real_target: body_block,
152+
unwind: Some(diverge_cleanup),
153+
},
149154
);
150-
this.diverge_from(loop_block);
151155

152156
// The “return” value of the loop body must always be an unit. We therefore
153157
// introduce a unit temporary as the destination for the loop body.
154158
let tmp = this.get_unit_temp();
155159
// Execute the body, branching back to the test.
156160
let body_block_end = unpack!(this.into(tmp, body_block, body));
157161
this.cfg.goto(body_block_end, source_info, loop_block);
158-
159-
// Loops are only exited by `break` expressions.
160-
None
161-
})
162+
});
163+
exit_block.unit()
162164
}
163165
ExprKind::Call { ty, fun, args, from_hir_call } => {
164166
let intrinsic = match ty.kind {
@@ -200,6 +202,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
200202
.collect();
201203

202204
let success = this.cfg.start_new_block();
205+
let cleanup = this.diverge_cleanup();
203206

204207
this.record_operands_moved(&args);
205208

@@ -209,7 +212,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
209212
TerminatorKind::Call {
210213
func: fun,
211214
args,
212-
cleanup: None,
215+
cleanup: Some(cleanup),
213216
// FIXME(varkor): replace this with an uninhabitedness-based check.
214217
// This requires getting access to the current module to call
215218
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
@@ -221,7 +224,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
221224
from_hir_call,
222225
},
223226
);
224-
this.diverge_from(block);
225227
success.unit()
226228
}
227229
}
@@ -425,12 +427,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
425427
let scope = this.local_scope();
426428
let value = unpack!(block = this.as_operand(block, scope, value));
427429
let resume = this.cfg.start_new_block();
430+
let cleanup = this.generator_drop_cleanup();
428431
this.cfg.terminate(
429432
block,
430433
source_info,
431-
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: None },
434+
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: cleanup },
432435
);
433-
this.generator_drop_cleanup(block);
434436
resume.unit()
435437
}
436438

src/librustc_mir_build/build/matches/mod.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
225225
outer_source_info: SourceInfo,
226226
fake_borrow_temps: Vec<(Place<'tcx>, Local)>,
227227
) -> BlockAnd<()> {
228+
let match_scope = self.scopes.topmost();
229+
228230
let arm_end_blocks: Vec<_> = arm_candidates
229231
.into_iter()
230232
.map(|(arm, candidate)| {
@@ -245,7 +247,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
245247
let arm_block = this.bind_pattern(
246248
outer_source_info,
247249
candidate,
248-
arm.guard.as_ref(),
250+
arm.guard.as_ref().map(|g| (g, match_scope)),
249251
&fake_borrow_temps,
250252
scrutinee_span,
251253
Some(arm.scope),
@@ -282,7 +284,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
282284
&mut self,
283285
outer_source_info: SourceInfo,
284286
candidate: Candidate<'_, 'tcx>,
285-
guard: Option<&Guard<'tcx>>,
287+
guard: Option<(&Guard<'tcx>, region::Scope)>,
286288
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
287289
scrutinee_span: Span,
288290
arm_scope: Option<region::Scope>,
@@ -1588,7 +1590,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15881590
&mut self,
15891591
candidate: Candidate<'pat, 'tcx>,
15901592
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
1591-
guard: Option<&Guard<'tcx>>,
1593+
guard: Option<(&Guard<'tcx>, region::Scope)>,
15921594
fake_borrows: &Vec<(Place<'tcx>, Local)>,
15931595
scrutinee_span: Span,
15941596
schedule_drops: bool,
@@ -1700,7 +1702,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17001702
// the reference that we create for the arm.
17011703
// * So we eagerly create the reference for the arm and then take a
17021704
// reference to that.
1703-
if let Some(guard) = guard {
1705+
if let Some((guard, region_scope)) = guard {
17041706
let tcx = self.hir.tcx();
17051707
let bindings = parent_bindings
17061708
.iter()
@@ -1744,7 +1746,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17441746
unreachable
17451747
});
17461748
let outside_scope = self.cfg.start_new_block();
1747-
self.exit_top_scope(otherwise_post_guard_block, outside_scope, source_info);
1749+
self.exit_scope(
1750+
source_info.span,
1751+
region_scope,
1752+
otherwise_post_guard_block,
1753+
outside_scope,
1754+
);
17481755
self.false_edges(
17491756
outside_scope,
17501757
otherwise_block,

src/librustc_mir_build/build/matches/test.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
423423
let bool_ty = self.hir.bool_ty();
424424
let eq_result = self.temp(bool_ty, source_info.span);
425425
let eq_block = self.cfg.start_new_block();
426+
let cleanup = self.diverge_cleanup();
426427
self.cfg.terminate(
427428
block,
428429
source_info,
@@ -439,12 +440,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
439440
literal: method,
440441
}),
441442
args: vec![val, expect],
442-
destination: Some((eq_result.clone(), eq_block)),
443-
cleanup: None,
443+
destination: Some((eq_result, eq_block)),
444+
cleanup: Some(cleanup),
444445
from_hir_call: false,
445446
},
446447
);
447-
self.diverge_from(block);
448448

449449
if let [success_block, fail_block] = *make_target_blocks(self) {
450450
// check the result

src/librustc_mir_build/build/mod.rs

+63-28
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ struct Builder<'a, 'tcx> {
327327

328328
var_debug_info: Vec<VarDebugInfo<'tcx>>,
329329

330+
/// Cached block with the `RESUME` terminator; this is created
331+
/// when first set of cleanups are built.
332+
cached_resume_block: Option<BasicBlock>,
333+
/// Cached block with the `RETURN` terminator.
334+
cached_return_block: Option<BasicBlock>,
330335
/// Cached block with the `UNREACHABLE` terminator.
331336
cached_unreachable_block: Option<BasicBlock>,
332337
}
@@ -585,34 +590,50 @@ where
585590
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
586591
let arg_scope =
587592
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
593+
let mut block = START_BLOCK;
588594
let source_info = builder.source_info(span);
589595
let call_site_s = (call_site_scope, source_info);
590-
unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
591-
let arg_scope_s = (arg_scope, source_info);
592-
// Attribute epilogue to function's closing brace
593-
let fn_end = span.shrink_to_hi();
594-
let return_block =
595-
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
596-
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
597-
builder.args_and_body(
598-
START_BLOCK,
599-
fn_def_id.to_def_id(),
600-
&arguments,
601-
arg_scope,
602-
&body.value,
603-
)
604-
}))
605-
}));
606-
let source_info = builder.source_info(fn_end);
607-
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
608-
let should_abort = should_abort_on_panic(tcx, fn_def_id, abi);
609-
builder.build_drop_trees(should_abort);
610-
// Attribute any unreachable codepaths to the function's closing brace
611-
if let Some(unreachable_block) = builder.cached_unreachable_block {
612-
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
613-
}
614-
return_block.unit()
615-
}));
596+
unpack!(
597+
block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
598+
if should_abort_on_panic(tcx, fn_def_id, abi) {
599+
builder.schedule_abort();
600+
}
601+
602+
let arg_scope_s = (arg_scope, source_info);
603+
// `return_block` is called when we evaluate a `return` expression, so
604+
// we just use `START_BLOCK` here.
605+
unpack!(
606+
block = builder.in_breakable_scope(
607+
None,
608+
START_BLOCK,
609+
Place::return_place(),
610+
|builder| {
611+
builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
612+
builder.args_and_body(
613+
block,
614+
fn_def_id.to_def_id(),
615+
&arguments,
616+
arg_scope,
617+
&body.value,
618+
)
619+
})
620+
},
621+
)
622+
);
623+
// Attribute epilogue to function's closing brace
624+
let fn_end = span.shrink_to_hi();
625+
let source_info = builder.source_info(fn_end);
626+
let return_block = builder.return_block();
627+
builder.cfg.goto(block, source_info, return_block);
628+
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
629+
// Attribute any unreachable codepaths to the function's closing brace
630+
if let Some(unreachable_block) = builder.cached_unreachable_block {
631+
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
632+
}
633+
return_block.unit()
634+
})
635+
);
636+
assert_eq!(block, builder.return_block());
616637

617638
let spread_arg = if abi == Abi::RustCall {
618639
// RustCall pseudo-ABI untuples the last argument.
@@ -646,7 +667,8 @@ fn construct_const<'a, 'tcx>(
646667
let source_info = builder.source_info(span);
647668
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
648669

649-
builder.build_drop_trees(false);
670+
// Constants can't `return` so a return block should not be created.
671+
assert_eq!(builder.cached_return_block, None);
650672

651673
// Constants may be match expressions in which case an unreachable block may
652674
// be created, so terminate it properly.
@@ -713,7 +735,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
713735
fn_span: span,
714736
arg_count,
715737
generator_kind,
716-
scopes: scope::Scopes::new(),
738+
scopes: Default::default(),
717739
block_context: BlockContext::new(),
718740
source_scopes: IndexVec::new(),
719741
source_scope: OUTERMOST_SOURCE_SCOPE,
@@ -726,6 +748,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
726748
var_indices: Default::default(),
727749
unit_temp: None,
728750
var_debug_info: vec![],
751+
cached_resume_block: None,
752+
cached_return_block: None,
729753
cached_unreachable_block: None,
730754
};
731755

@@ -957,6 +981,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
957981
}
958982
}
959983
}
984+
985+
fn return_block(&mut self) -> BasicBlock {
986+
match self.cached_return_block {
987+
Some(rb) => rb,
988+
None => {
989+
let rb = self.cfg.start_new_block();
990+
self.cached_return_block = Some(rb);
991+
rb
992+
}
993+
}
994+
}
960995
}
961996

962997
///////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)