Skip to content

Commit 00d1590

Browse files
committedSep 16, 2019
adjust desugaring for async fn to correct drop order
Old desugaring, given a user function body { $stmts; $expr } ``` { let $param_pattern0 = $raw_param0; ... let $param_patternN = $raw_paramN; $stmts; $expr } ``` New desugaring: ``` { let $param_pattern0 = $raw_param0; ... let $param_patternN = $raw_paramN; drop-temps { $stmts; $expr } } ``` The drop-temps is an internal bit of HIR that drops temporaries from the resulting expression, but it should be equivalent to `return { $stmts; $expr }`.
1 parent 9ae1a66 commit 00d1590

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed
 

Diff for: ‎src/librustc/hir/lowering.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -2682,12 +2682,8 @@ impl<'a> LoweringContext<'a> {
26822682
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
26832683
}
26842684

2685-
fn lower_block_with_stmts(
2686-
&mut self,
2687-
b: &Block,
2688-
targeted_by_break: bool,
2689-
mut stmts: Vec<hir::Stmt>,
2690-
) -> P<hir::Block> {
2685+
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
2686+
let mut stmts = vec![];
26912687
let mut expr = None;
26922688

26932689
for (index, stmt) in b.stmts.iter().enumerate() {
@@ -2712,10 +2708,6 @@ impl<'a> LoweringContext<'a> {
27122708
})
27132709
}
27142710

2715-
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
2716-
self.lower_block_with_stmts(b, targeted_by_break, vec![])
2717-
}
2718-
27192711
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
27202712
let node = match p.node {
27212713
PatKind::Wild => hir::PatKind::Wild,

Diff for: ‎src/librustc/hir/lowering/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ impl LoweringContext<'_> {
13101310
/// `{ let _t = $expr; _t }` but should provide better compile-time performance.
13111311
///
13121312
/// The drop order can be important in e.g. `if expr { .. }`.
1313-
fn expr_drop_temps(
1313+
pub(super) fn expr_drop_temps(
13141314
&mut self,
13151315
span: Span,
13161316
expr: P<hir::Expr>,

Diff for: ‎src/librustc/hir/lowering/item.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -1219,8 +1219,44 @@ impl LoweringContext<'_> {
12191219
let async_expr = this.make_async_expr(
12201220
CaptureBy::Value, closure_id, None, body.span,
12211221
|this| {
1222-
let body = this.lower_block_with_stmts(body, false, statements);
1223-
this.expr_block(body, ThinVec::new())
1222+
// Create a block from the user's function body:
1223+
let user_body = this.lower_block(body, false);
1224+
let user_body = this.expr_block(user_body, ThinVec::new());
1225+
1226+
// Transform into `drop-temps { <user-body> }`, an expression:
1227+
let desugared_span = this.mark_span_with_reason(
1228+
DesugaringKind::Async,
1229+
user_body.span,
1230+
None,
1231+
);
1232+
let user_body = this.expr_drop_temps(
1233+
desugared_span,
1234+
P(user_body),
1235+
ThinVec::new(),
1236+
);
1237+
1238+
// Create a block like
1239+
//
1240+
// ```
1241+
// {
1242+
// let $param_pattern = $raw_param;
1243+
// ...
1244+
// drop-temps { <user-body> }
1245+
// }
1246+
// ```
1247+
//
1248+
// This construction is carefully calibrated to
1249+
// get the drop-order correct. In particular, the
1250+
// drop-temps ensures that any temporaries in the
1251+
// tail expression of `<user-body>` are dropped
1252+
// *before* the parameters are dropped (see
1253+
// rust-lang/rust#64512).
1254+
let body = this.block_all(
1255+
desugared_span,
1256+
statements.into(),
1257+
Some(P(user_body)),
1258+
);
1259+
this.expr_block(P(body), ThinVec::new())
12241260
});
12251261
(HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
12261262
})

0 commit comments

Comments
 (0)
Please sign in to comment.