Skip to content

Commit d3e2cec

Browse files
committed
Auto merge of #61872 - matthewjasper:refactor-mir-drop-gen, r=nikomatsakis
Clean up MIR drop generation * Don't assign twice to the destination of a `while` loop containing a `break` expression * Use `as_temp` to evaluate statement expression * Avoid consecutive `StorageLive`s for the condition of a `while` loop * Unify `return`, `break` and `continue` handling, and move it to `scopes.rs` * Make some of the `scopes.rs` internals private * Don't use `Place`s that are always `Local`s in MIR drop generation Closes #42371 Closes #61579 Closes #61731 Closes #61834 Closes #61910 Closes #62115
2 parents bdd4bda + 3131427 commit d3e2cec

27 files changed

+536
-468
lines changed

src/librustc_mir/build/block.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7878

7979
let source_info = this.source_info(span);
8080
for stmt in stmts {
81-
let Stmt { kind, opt_destruction_scope, span: stmt_span } = this.hir.mirror(stmt);
81+
let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
8282
match kind {
8383
StmtKind::Expr { scope, expr } => {
8484
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
@@ -87,7 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8787
let si = (scope, source_info);
8888
this.in_scope(si, LintLevel::Inherited, |this| {
8989
let expr = this.hir.mirror(expr);
90-
this.stmt_expr(block, expr, Some(stmt_span))
90+
this.stmt_expr(block, expr, Some(scope))
9191
})
9292
}));
9393
}

src/librustc_mir/build/expr/as_rvalue.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127127
this.schedule_drop_storage_and_value(
128128
expr_span,
129129
scope,
130-
&Place::from(result),
130+
result,
131131
value.ty,
132132
);
133133
}
@@ -559,7 +559,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
559559
this.schedule_drop_storage_and_value(
560560
upvar_span,
561561
temp_lifetime,
562-
&Place::from(temp),
562+
temp,
563563
upvar_ty,
564564
);
565565
}

src/librustc_mir/build/expr/as_temp.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8888
this.schedule_drop(
8989
expr_span,
9090
temp_lifetime,
91-
temp_place,
91+
temp,
9292
expr_ty,
9393
DropKind::Storage,
9494
);
@@ -101,7 +101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
101101
this.schedule_drop(
102102
expr_span,
103103
temp_lifetime,
104-
temp_place,
104+
temp,
105105
expr_ty,
106106
DropKind::Value,
107107
);

src/librustc_mir/build/expr/into.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -179,20 +179,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
179179
// conduct the test, if necessary
180180
let body_block;
181181
if let Some(cond_expr) = opt_cond_expr {
182-
let loop_block_end;
183-
let cond = unpack!(
184-
loop_block_end = this.as_local_operand(loop_block, cond_expr)
185-
);
186-
body_block = this.cfg.start_new_block();
187-
let term =
188-
TerminatorKind::if_(this.hir.tcx(), cond, body_block, exit_block);
189-
this.cfg.terminate(loop_block_end, source_info, term);
182+
let cond_expr = this.hir.mirror(cond_expr);
183+
let (true_block, false_block)
184+
= this.test_bool(loop_block, cond_expr, source_info);
185+
body_block = true_block;
190186

191187
// if the test is false, there's no `break` to assign `destination`, so
192-
// we have to do it; this overwrites any `break`-assigned value but it's
193-
// always `()` anyway
194-
this.cfg
195-
.push_assign_unit(exit_block, source_info, destination);
188+
// we have to do it
189+
this.cfg.push_assign_unit(false_block, source_info, destination);
190+
this.cfg.terminate(
191+
false_block,
192+
source_info,
193+
TerminatorKind::Goto { target: exit_block },
194+
);
196195
} else {
197196
body_block = this.cfg.start_new_block();
198197
let diverge_cleanup = this.diverge_cleanup();

src/librustc_mir/build/expr/stmt.rs

+39-106
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
use crate::build::scope::BreakableScope;
1+
use crate::build::scope::BreakableTarget;
22
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
33
use crate::hair::*;
4+
use rustc::middle::region;
45
use rustc::mir::*;
56

67
impl<'a, 'tcx> Builder<'a, 'tcx> {
78
/// Builds a block of MIR statements to evaluate the HAIR `expr`.
89
/// If the original expression was an AST statement,
910
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
1011
/// span of that statement (including its semicolon, if any).
11-
/// Diagnostics use this span (which may be larger than that of
12-
/// `expr`) to identify when statement temporaries are dropped.
13-
pub fn stmt_expr(&mut self,
14-
mut block: BasicBlock,
15-
expr: Expr<'tcx>,
16-
opt_stmt_span: Option<StatementSpan>)
17-
-> BlockAnd<()>
18-
{
12+
/// The scope is used if a statement temporary must be dropped.
13+
pub fn stmt_expr(
14+
&mut self,
15+
mut block: BasicBlock,
16+
expr: Expr<'tcx>,
17+
statement_scope: Option<region::Scope>,
18+
) -> BlockAnd<()> {
1919
let this = self;
2020
let expr_span = expr.span;
2121
let source_info = this.source_info(expr.span);
@@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3030
} => {
3131
let value = this.hir.mirror(value);
3232
this.in_scope((region_scope, source_info), lint_level, |this| {
33-
this.stmt_expr(block, value, opt_stmt_span)
33+
this.stmt_expr(block, value, statement_scope)
3434
})
3535
}
3636
ExprKind::Assign { lhs, rhs } => {
@@ -98,70 +98,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9898
block.unit()
9999
}
100100
ExprKind::Continue { label } => {
101-
let BreakableScope {
102-
continue_block,
103-
region_scope,
104-
..
105-
} = *this.find_breakable_scope(expr_span, label);
106-
let continue_block = continue_block
107-
.expect("Attempted to continue in non-continuable breakable block");
108-
this.exit_scope(
109-
expr_span,
110-
(region_scope, source_info),
111-
block,
112-
continue_block,
113-
);
114-
this.cfg.start_new_block().unit()
101+
this.break_scope(block, None, BreakableTarget::Continue(label), source_info)
115102
}
116103
ExprKind::Break { label, value } => {
117-
let (break_block, region_scope, destination) = {
118-
let BreakableScope {
119-
break_block,
120-
region_scope,
121-
ref break_destination,
122-
..
123-
} = *this.find_breakable_scope(expr_span, label);
124-
(break_block, region_scope, break_destination.clone())
125-
};
126-
if let Some(value) = value {
127-
debug!("stmt_expr Break val block_context.push(SubExpr) : {:?}", expr2);
128-
this.block_context.push(BlockFrame::SubExpr);
129-
unpack!(block = this.into(&destination, block, value));
130-
this.block_context.pop();
131-
} else {
132-
this.cfg.push_assign_unit(block, source_info, &destination)
133-
}
134-
this.exit_scope(expr_span, (region_scope, source_info), block, break_block);
135-
this.cfg.start_new_block().unit()
104+
this.break_scope(block, value, BreakableTarget::Break(label), source_info)
136105
}
137106
ExprKind::Return { value } => {
138-
block = match value {
139-
Some(value) => {
140-
debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
141-
this.block_context.push(BlockFrame::SubExpr);
142-
let result = unpack!(
143-
this.into(
144-
&Place::RETURN_PLACE,
145-
block,
146-
value
147-
)
148-
);
149-
this.block_context.pop();
150-
result
151-
}
152-
None => {
153-
this.cfg.push_assign_unit(
154-
block,
155-
source_info,
156-
&Place::RETURN_PLACE,
157-
);
158-
block
159-
}
160-
};
161-
let region_scope = this.region_scope_of_return_scope();
162-
let return_block = this.return_block();
163-
this.exit_scope(expr_span, (region_scope, source_info), block, return_block);
164-
this.cfg.start_new_block().unit()
107+
this.break_scope(block, value, BreakableTarget::Return, source_info)
165108
}
166109
ExprKind::InlineAsm {
167110
asm,
@@ -199,7 +142,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
199142
block.unit()
200143
}
201144
_ => {
202-
let expr_ty = expr.ty;
145+
assert!(
146+
statement_scope.is_some(),
147+
"Should not be calling `stmt_expr` on a general expression \
148+
without a statement scope",
149+
);
203150

204151
// Issue #54382: When creating temp for the value of
205152
// expression like:
@@ -208,48 +155,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
208155
//
209156
// it is usually better to focus on `the_value` rather
210157
// than the entirety of block(s) surrounding it.
211-
let mut temp_span = expr_span;
212-
let mut temp_in_tail_of_block = false;
213-
if let ExprKind::Block { body } = expr.kind {
214-
if let Some(tail_expr) = &body.expr {
215-
let mut expr = tail_expr;
216-
while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
217-
if let Some(subtail_expr) = &subblock.expr {
218-
expr = subtail_expr
219-
} else {
220-
break;
158+
let adjusted_span = (|| {
159+
if let ExprKind::Block { body } = expr.kind {
160+
if let Some(tail_expr) = &body.expr {
161+
let mut expr = tail_expr;
162+
while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
163+
if let Some(subtail_expr) = &subblock.expr {
164+
expr = subtail_expr
165+
} else {
166+
break;
167+
}
221168
}
222-
}
223-
temp_span = expr.span;
224-
temp_in_tail_of_block = true;
225-
}
226-
}
227-
228-
let temp = {
229-
let mut local_decl = LocalDecl::new_temp(expr.ty.clone(), temp_span);
230-
if temp_in_tail_of_block {
231-
if this.block_context.currently_ignores_tail_results() {
232-
local_decl = local_decl.block_tail(BlockTailInfo {
169+
this.block_context.push(BlockFrame::TailExpr {
233170
tail_result_is_ignored: true
234171
});
172+
return Some(expr.span);
235173
}
236174
}
237-
let temp = this.local_decls.push(local_decl);
238-
let place = Place::from(temp);
239-
debug!("created temp {:?} for expr {:?} in block_context: {:?}",
240-
temp, expr, this.block_context);
241-
place
242-
};
243-
unpack!(block = this.into(&temp, block, expr));
175+
None
176+
})();
244177

245-
// Attribute drops of the statement's temps to the
246-
// semicolon at the statement's end.
247-
let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
248-
None => expr_span,
249-
Some(StatementSpan(span)) => span,
250-
});
178+
let temp = unpack!(block =
179+
this.as_temp(block, statement_scope, expr, Mutability::Not));
180+
181+
if let Some(span) = adjusted_span {
182+
this.local_decls[temp].source_info.span = span;
183+
this.block_context.pop();
184+
}
251185

252-
unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
253186
block.unit()
254187
}
255188
}

0 commit comments

Comments
 (0)