Skip to content

Commit 1f5fb7b

Browse files
committed
Make into schedule drop for the destination again
1 parent cb7c75b commit 1f5fb7b

File tree

12 files changed

+648
-358
lines changed

12 files changed

+648
-358
lines changed

src/librustc_mir_build/build/block.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ use crate::build::matches::ArmHasGuard;
22
use crate::build::ForGuard::OutsideGuard;
33
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
44
use crate::hair::*;
5+
use rustc::middle::region;
56
use rustc::mir::*;
67
use rustc_hir as hir;
78
use rustc_span::Span;
89

910
impl<'a, 'tcx> Builder<'a, 'tcx> {
10-
crate fn ast_block(
11+
pub fn ast_block(
1112
&mut self,
1213
destination: &Place<'tcx>,
14+
scope: Option<region::Scope>,
1315
block: BasicBlock,
1416
ast_block: &'tcx hir::Block<'tcx>,
1517
source_info: SourceInfo,
@@ -26,9 +28,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2628
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
2729
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
2830
if targeted_by_break {
29-
this.in_breakable_scope(None, destination.clone(), span, |this| {
31+
this.in_breakable_scope(None, destination.clone(), scope, span, |this| {
3032
Some(this.ast_block_stmts(
3133
destination,
34+
scope,
3235
block,
3336
span,
3437
stmts,
@@ -37,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3740
))
3841
})
3942
} else {
40-
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
43+
this.ast_block_stmts(destination, scope, block, span, stmts, expr, safety_mode)
4144
}
4245
})
4346
})
@@ -46,6 +49,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4649
fn ast_block_stmts(
4750
&mut self,
4851
destination: &Place<'tcx>,
52+
scope: Option<region::Scope>,
4953
mut block: BasicBlock,
5054
span: Span,
5155
stmts: Vec<StmtRef<'tcx>>,
@@ -177,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
177181
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
178182
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
179183

180-
unpack!(block = this.into(destination, block, expr));
184+
unpack!(block = this.into(destination, scope, block, expr));
181185
let popped = this.block_context.pop();
182186

183187
assert!(popped.map_or(false, |bf| bf.is_tail_expr()));

src/librustc_mir_build/build/expr/as_rvalue.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
111111
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
112112
this.cfg.push_assign(block, source_info, &Place::from(result), box_);
113113

114-
// initialize the box contents:
114+
// Initialize the box contents. No scope is needed since the
115+
// `Box` is already scheduled to be dropped.
115116
unpack!(
116117
block = this.into(
117118
&this.hir.tcx().mk_place_deref(Place::from(result)),
119+
None,
118120
block,
119-
value
121+
value,
120122
)
121123
);
122124
block.and(Rvalue::Use(Operand::Move(Place::from(result))))

src/librustc_mir_build/build/expr/as_temp.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
100100
}
101101
}
102102

103-
unpack!(block = this.into(temp_place, block, expr));
104-
105-
if let Some(temp_lifetime) = temp_lifetime {
106-
this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
107-
}
103+
unpack!(block = this.into(temp_place, temp_lifetime, block, expr));
108104

109105
block.and(temp)
110106
}

src/librustc_mir_build/build/expr/into.rs

+47-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! See docs in build/expr/mod.rs
22
33
use crate::build::expr::category::{Category, RvalueFunc};
4+
use crate::build::scope::DropKind;
45
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
56
use crate::hair::*;
7+
use rustc::middle::region;
68
use rustc::mir::*;
79
use rustc::ty::{self, CanonicalUserTypeAnnotation};
810
use rustc_data_structures::fx::FxHashMap;
@@ -14,13 +16,19 @@ use rustc_target::spec::abi::Abi;
1416
impl<'a, 'tcx> Builder<'a, 'tcx> {
1517
/// Compile `expr`, storing the result into `destination`, which
1618
/// is assumed to be uninitialized.
19+
/// If a `drop_scope` is provided, `destination` is scheduled to be dropped
20+
/// in `scope` once it has been initialized.
1721
crate fn into_expr(
1822
&mut self,
1923
destination: &Place<'tcx>,
24+
scope: Option<region::Scope>,
2025
mut block: BasicBlock,
2126
expr: Expr<'tcx>,
2227
) -> BlockAnd<()> {
23-
debug!("into_expr(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
28+
debug!(
29+
"into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})",
30+
destination, scope, block, expr
31+
);
2432

2533
// since we frequently have to reference `self` from within a
2634
// closure, where `self` would be shadowed, it's easier to
@@ -35,20 +43,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3543
_ => false,
3644
};
3745

46+
let schedule_drop = move |this: &mut Self| {
47+
if let Some(drop_scope) = scope {
48+
let local =
49+
destination.as_local().expect("cannot schedule drop of non-Local place");
50+
this.schedule_drop(expr_span, drop_scope, local, DropKind::Value);
51+
}
52+
};
53+
3854
if !expr_is_block_or_scope {
3955
this.block_context.push(BlockFrame::SubExpr);
4056
}
4157

4258
let block_and = match expr.kind {
4359
ExprKind::Scope { region_scope, lint_level, value } => {
4460
let region_scope = (region_scope, source_info);
45-
this.in_scope(region_scope, lint_level, |this| this.into(destination, block, value))
61+
this.in_scope(region_scope, lint_level, |this| {
62+
this.into(destination, scope, block, value)
63+
})
4664
}
4765
ExprKind::Block { body: ast_block } => {
48-
this.ast_block(destination, block, ast_block, source_info)
66+
this.ast_block(destination, scope, block, ast_block, source_info)
4967
}
5068
ExprKind::Match { scrutinee, arms } => {
51-
this.match_expr(destination, expr_span, block, scrutinee, arms)
69+
this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
5270
}
5371
ExprKind::NeverToAny { source } => {
5472
let source = this.hir.mirror(source);
@@ -63,6 +81,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6381

6482
// This is an optimization. If the expression was a call then we already have an
6583
// unreachable block. Don't bother to terminate it and create a new one.
84+
schedule_drop(this);
6685
if is_call {
6786
block.unit()
6887
} else {
@@ -141,6 +160,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
141160
this.in_breakable_scope(
142161
Some(loop_block),
143162
destination.clone(),
163+
scope,
144164
expr_span,
145165
move |this| {
146166
// conduct the test, if necessary
@@ -156,8 +176,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
156176
// introduce a unit temporary as the destination for the loop body.
157177
let tmp = this.get_unit_temp();
158178
// Execute the body, branching back to the test.
159-
let body_block_end = unpack!(this.into(&tmp, body_block, body));
160-
this.cfg.goto(body_block_end, source_info, loop_block);
179+
// No scope is provided, since we've scheduled the drop above.
180+
let body_block_end = unpack!(this.into(&tmp, None, body_block, body));
181+
this.cfg.terminate(
182+
body_block_end,
183+
source_info,
184+
TerminatorKind::Goto { target: loop_block },
185+
);
186+
schedule_drop(this);
161187
None
162188
},
163189
)
@@ -198,8 +224,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
198224
is_block_tail: None,
199225
});
200226
let ptr_temp = Place::from(ptr_temp);
201-
let block = unpack!(this.into(&ptr_temp, block, ptr));
202-
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), block, val)
227+
// No need for a scope, ptr_temp doesn't need drop
228+
let block = unpack!(this.into(&ptr_temp, None, block, ptr));
229+
// Maybe we should provide a scope here so that
230+
// `move_val_init` wouldn't leak on panic even with an
231+
// arbitrary `val` expression, but `schedule_drop`,
232+
// borrowck and drop elaboration all prevent us from
233+
// dropping `ptr_temp.deref()`.
234+
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), None, block, val)
203235
} else {
204236
let args: Vec<_> = args
205237
.into_iter()
@@ -229,10 +261,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
229261
from_hir_call,
230262
},
231263
);
264+
schedule_drop(this);
232265
success.unit()
233266
}
234267
}
235-
ExprKind::Use { source } => this.into(destination, block, source),
268+
ExprKind::Use { source } => this.into(destination, scope, block, source),
236269
ExprKind::Borrow { arg, borrow_kind } => {
237270
// We don't do this in `as_rvalue` because we use `as_place`
238271
// for borrow expressions, so we cannot create an `RValue` that
@@ -316,6 +349,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
316349
destination,
317350
Rvalue::Aggregate(adt, fields),
318351
);
352+
schedule_drop(this);
319353
block.unit()
320354
}
321355

@@ -341,6 +375,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
341375
let place = unpack!(block = this.as_place(block, expr));
342376
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
343377
this.cfg.push_assign(block, source_info, destination, rvalue);
378+
schedule_drop(this);
344379
block.unit()
345380
}
346381
ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => {
@@ -358,6 +393,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
358393
let place = unpack!(block = this.as_place(block, expr));
359394
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
360395
this.cfg.push_assign(block, source_info, destination, rvalue);
396+
schedule_drop(this);
361397
block.unit()
362398
}
363399

@@ -371,6 +407,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
371407
source_info,
372408
TerminatorKind::Yield { value, resume, resume_arg: *destination, drop: None },
373409
);
410+
schedule_drop(this);
374411
resume.unit()
375412
}
376413

@@ -400,6 +437,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
400437

401438
let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
402439
this.cfg.push_assign(block, source_info, destination, rvalue);
440+
schedule_drop(this);
403441
block.unit()
404442
}
405443
};

src/librustc_mir_build/build/into.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,31 @@
66
77
use crate::build::{BlockAnd, Builder};
88
use crate::hair::*;
9+
use rustc::middle::region;
910
use rustc::mir::*;
1011

1112
pub(in crate::build) trait EvalInto<'tcx> {
1213
fn eval_into(
1314
self,
1415
builder: &mut Builder<'_, 'tcx>,
1516
destination: &Place<'tcx>,
17+
scope: Option<region::Scope>,
1618
block: BasicBlock,
1719
) -> BlockAnd<()>;
1820
}
1921

2022
impl<'a, 'tcx> Builder<'a, 'tcx> {
21-
crate fn into<E>(
23+
pub fn into<E>(
2224
&mut self,
2325
destination: &Place<'tcx>,
26+
scope: Option<region::Scope>,
2427
block: BasicBlock,
2528
expr: E,
2629
) -> BlockAnd<()>
2730
where
2831
E: EvalInto<'tcx>,
2932
{
30-
expr.eval_into(self, destination, block)
33+
expr.eval_into(self, destination, scope, block)
3134
}
3235
}
3336

@@ -36,10 +39,11 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
3639
self,
3740
builder: &mut Builder<'_, 'tcx>,
3841
destination: &Place<'tcx>,
42+
scope: Option<region::Scope>,
3943
block: BasicBlock,
4044
) -> BlockAnd<()> {
4145
let expr = builder.hir.mirror(self);
42-
builder.into_expr(destination, block, expr)
46+
builder.into_expr(destination, scope, block, expr)
4347
}
4448
}
4549

@@ -48,8 +52,9 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
4852
self,
4953
builder: &mut Builder<'_, 'tcx>,
5054
destination: &Place<'tcx>,
55+
scope: Option<region::Scope>,
5156
block: BasicBlock,
5257
) -> BlockAnd<()> {
53-
builder.into_expr(destination, block, self)
58+
builder.into_expr(destination, scope, block, self)
5459
}
5560
}

0 commit comments

Comments
 (0)