Skip to content

Commit 6119885

Browse files
committed
Defer creating drop trees in MIR lowering until leaving that scope
1 parent 945d110 commit 6119885

File tree

8 files changed

+766
-735
lines changed

8 files changed

+766
-735
lines changed

src/librustc_mir/util/graphviz.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,17 @@ 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+
};
100105
write!(
101106
w,
102-
r#"<tr><td {attrs} colspan="{colspan}">{blk}</td></tr>"#,
103-
attrs = r#"bgcolor="gray" align="center""#,
107+
r#"<tr><td bgcolor="{color}" align="center" colspan="{colspan}">{blk}</td></tr>"#,
104108
colspan = num_cols,
105-
blk = block.index()
109+
blk = blk,
110+
color = color
106111
)?;
107112

108113
init(w)?;

src/librustc_mir_build/build/block.rs

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

src/librustc_mir_build/build/expr/into.rs

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

136136
let loop_block = this.cfg.start_new_block();
137-
let exit_block = this.cfg.start_new_block();
138137

139138
// Start the loop.
140139
this.cfg.goto(block, source_info, loop_block);
141140

142-
this.in_breakable_scope(Some(loop_block), exit_block, destination, move |this| {
141+
this.in_breakable_scope(Some(loop_block), destination, expr_span, move |this| {
143142
// conduct the test, if necessary
144143
let body_block = this.cfg.start_new_block();
145-
let diverge_cleanup = this.diverge_cleanup();
146144
this.cfg.terminate(
147145
loop_block,
148146
source_info,
149-
TerminatorKind::FalseUnwind {
150-
real_target: body_block,
151-
unwind: Some(diverge_cleanup),
152-
},
147+
TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
153148
);
149+
this.diverge_from(loop_block);
154150

155151
// The “return” value of the loop body must always be an unit. We therefore
156152
// introduce a unit temporary as the destination for the loop body.
157153
let tmp = this.get_unit_temp();
158154
// Execute the body, branching back to the test.
159155
let body_block_end = unpack!(this.into(tmp, body_block, body));
160156
this.cfg.goto(body_block_end, source_info, loop_block);
161-
});
162-
exit_block.unit()
157+
158+
// Loops are only exited by `break` expressions.
159+
None
160+
})
163161
}
164162
ExprKind::Call { ty, fun, args, from_hir_call } => {
165163
let intrinsic = match ty.kind {
@@ -201,7 +199,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
201199
.collect();
202200

203201
let success = this.cfg.start_new_block();
204-
let cleanup = this.diverge_cleanup();
205202

206203
this.record_operands_moved(&args);
207204

@@ -211,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
211208
TerminatorKind::Call {
212209
func: fun,
213210
args,
214-
cleanup: Some(cleanup),
211+
cleanup: None,
215212
// FIXME(varkor): replace this with an uninhabitedness-based check.
216213
// This requires getting access to the current module to call
217214
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
@@ -223,6 +220,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
223220
from_hir_call,
224221
},
225222
);
223+
this.diverge_from(block);
226224
success.unit()
227225
}
228226
}
@@ -358,12 +356,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
358356
let scope = this.local_scope();
359357
let value = unpack!(block = this.as_operand(block, scope, value));
360358
let resume = this.cfg.start_new_block();
361-
let cleanup = this.generator_drop_cleanup();
362359
this.cfg.terminate(
363360
block,
364361
source_info,
365-
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: cleanup },
362+
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: None },
366363
);
364+
this.generator_drop_cleanup(block);
367365
resume.unit()
368366
}
369367

src/librustc_mir_build/build/matches/mod.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ 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-
230228
let arm_end_blocks: Vec<_> = arm_candidates
231229
.into_iter()
232230
.map(|(arm, candidate)| {
@@ -247,7 +245,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
247245
let arm_block = this.bind_pattern(
248246
outer_source_info,
249247
candidate,
250-
arm.guard.as_ref().map(|g| (g, match_scope)),
248+
arm.guard.as_ref(),
251249
&fake_borrow_temps,
252250
scrutinee_span,
253251
Some(arm.scope),
@@ -284,7 +282,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
284282
&mut self,
285283
outer_source_info: SourceInfo,
286284
candidate: Candidate<'_, 'tcx>,
287-
guard: Option<(&Guard<'tcx>, region::Scope)>,
285+
guard: Option<&Guard<'tcx>>,
288286
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
289287
scrutinee_span: Span,
290288
arm_scope: Option<region::Scope>,
@@ -1563,7 +1561,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15631561
&mut self,
15641562
candidate: Candidate<'pat, 'tcx>,
15651563
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
1566-
guard: Option<(&Guard<'tcx>, region::Scope)>,
1564+
guard: Option<&Guard<'tcx>>,
15671565
fake_borrows: &Vec<(Place<'tcx>, Local)>,
15681566
scrutinee_span: Span,
15691567
schedule_drops: bool,
@@ -1675,7 +1673,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16751673
// the reference that we create for the arm.
16761674
// * So we eagerly create the reference for the arm and then take a
16771675
// reference to that.
1678-
if let Some((guard, region_scope)) = guard {
1676+
if let Some(guard) = guard {
16791677
let tcx = self.hir.tcx();
16801678
let bindings = parent_bindings
16811679
.iter()
@@ -1719,12 +1717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17191717
unreachable
17201718
});
17211719
let outside_scope = self.cfg.start_new_block();
1722-
self.exit_scope(
1723-
source_info.span,
1724-
region_scope,
1725-
otherwise_post_guard_block,
1726-
outside_scope,
1727-
);
1720+
self.exit_top_scope(otherwise_post_guard_block, outside_scope, source_info);
17281721
self.false_edges(
17291722
outside_scope,
17301723
otherwise_block,

src/librustc_mir_build/build/matches/test.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,6 @@ 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();
427426
self.cfg.terminate(
428427
block,
429428
source_info,
@@ -440,11 +439,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
440439
literal: method,
441440
}),
442441
args: vec![val, expect],
443-
destination: Some((eq_result, eq_block)),
444-
cleanup: Some(cleanup),
442+
destination: Some((eq_result.clone(), eq_block)),
443+
cleanup: None,
445444
from_hir_call: false,
446445
},
447446
);
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

+28-63
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,6 @@ 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>,
335330
/// Cached block with the `UNREACHABLE` terminator.
336331
cached_unreachable_block: Option<BasicBlock>,
337332
}
@@ -590,50 +585,34 @@ where
590585
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
591586
let arg_scope =
592587
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
593-
let mut block = START_BLOCK;
594588
let source_info = builder.source_info(span);
595589
let call_site_s = (call_site_scope, source_info);
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());
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+
}));
637616

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

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

673651
// Constants may be match expressions in which case an unreachable block may
674652
// be created, so terminate it properly.
@@ -735,7 +713,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
735713
fn_span: span,
736714
arg_count,
737715
generator_kind,
738-
scopes: Default::default(),
716+
scopes: scope::Scopes::new(),
739717
block_context: BlockContext::new(),
740718
source_scopes: IndexVec::new(),
741719
source_scope: OUTERMOST_SOURCE_SCOPE,
@@ -748,8 +726,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
748726
var_indices: Default::default(),
749727
unit_temp: None,
750728
var_debug_info: vec![],
751-
cached_resume_block: None,
752-
cached_return_block: None,
753729
cached_unreachable_block: None,
754730
};
755731

@@ -981,17 +957,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
981957
}
982958
}
983959
}
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-
}
995960
}
996961

997962
///////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)