Skip to content

Commit 56b3bf2

Browse files
committed
Make into schedule drop for the destination again
1 parent 90916d0 commit 56b3bf2

File tree

12 files changed

+573
-289
lines changed

12 files changed

+573
-289
lines changed

src/librustc_mir/build/block.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
22
use crate::build::ForGuard::OutsideGuard;
33
use crate::build::matches::ArmHasGuard;
44
use crate::hair::*;
5+
use rustc::middle::region;
56
use rustc::mir::*;
67
use rustc::hir;
78
use syntax_pos::Span;
89

910
impl<'a, 'tcx> Builder<'a, 'tcx> {
10-
pub fn ast_block(&mut self,
11-
destination: &Place<'tcx>,
12-
block: BasicBlock,
13-
ast_block: &'tcx hir::Block,
14-
source_info: SourceInfo)
15-
-> BlockAnd<()> {
11+
pub fn ast_block(
12+
&mut self,
13+
destination: &Place<'tcx>,
14+
scope: Option<region::Scope>,
15+
block: BasicBlock,
16+
ast_block: &'tcx hir::Block,
17+
source_info: SourceInfo,
18+
) -> BlockAnd<()> {
1619
let Block {
1720
region_scope,
1821
opt_destruction_scope,
@@ -21,17 +24,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2124
expr,
2225
targeted_by_break,
2326
safety_mode
24-
} =
25-
self.hir.mirror(ast_block);
27+
} = self.hir.mirror(ast_block);
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 {
2931
this.in_breakable_scope(
3032
None,
3133
destination.clone(),
34+
scope,
3235
span,
3336
|this| Some(this.ast_block_stmts(
3437
destination,
38+
scope,
3539
block,
3640
span,
3741
stmts,
@@ -40,21 +44,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4044
)),
4145
)
4246
} else {
43-
this.ast_block_stmts(destination, block, span, stmts, expr,
44-
safety_mode)
47+
this.ast_block_stmts(
48+
destination,
49+
scope,
50+
block,
51+
span,
52+
stmts,
53+
expr,
54+
safety_mode,
55+
)
4556
}
4657
})
4758
})
4859
}
4960

50-
fn ast_block_stmts(&mut self,
51-
destination: &Place<'tcx>,
52-
mut block: BasicBlock,
53-
span: Span,
54-
stmts: Vec<StmtRef<'tcx>>,
55-
expr: Option<ExprRef<'tcx>>,
56-
safety_mode: BlockSafety)
57-
-> BlockAnd<()> {
61+
fn ast_block_stmts(
62+
&mut self,
63+
destination: &Place<'tcx>,
64+
scope: Option<region::Scope>,
65+
mut block: BasicBlock,
66+
span: Span,
67+
stmts: Vec<StmtRef<'tcx>>,
68+
expr: Option<ExprRef<'tcx>>,
69+
safety_mode: BlockSafety,
70+
) -> BlockAnd<()> {
5871
let this = self;
5972

6073
// This convoluted structure is to avoid using recursion as we walk down a list
@@ -180,7 +193,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
180193
this.block_context.currently_ignores_tail_results();
181194
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
182195

183-
unpack!(block = this.into(destination, block, expr));
196+
unpack!(block = this.into(destination, scope, block, expr));
184197
let popped = this.block_context.pop();
185198

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

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
130130
this.cfg
131131
.push_assign(block, source_info, &Place::from(result), box_);
132132

133-
// initialize the box contents:
133+
// Initialize the box contents. No scope is needed since the
134+
// `Box` is already scheduled to be dropped.
134135
unpack!(
135136
block = this.into(
136137
&this.hir.tcx().mk_place_deref(Place::from(result)),
137-
block, value
138+
None,
139+
block,
140+
value,
138141
)
139142
);
140143
block.and(Rvalue::Use(Operand::Move(Place::from(result))))

src/librustc_mir/build/expr/as_temp.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
114114
}
115115
}
116116

117-
unpack!(block = this.into(temp_place, block, expr));
118-
119-
if let Some(temp_lifetime) = temp_lifetime {
120-
this.schedule_drop(
121-
expr_span,
122-
temp_lifetime,
123-
temp,
124-
DropKind::Value,
125-
);
126-
}
117+
unpack!(block = this.into(temp_place, temp_lifetime, block, expr));
127118

128119
block.and(temp)
129120
}

src/librustc_mir/build/expr/into.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
33
use crate::build::expr::category::{Category, RvalueFunc};
44
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
5+
use crate::build::scope::DropKind;
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;
@@ -13,15 +15,18 @@ use rustc_target::spec::abi::Abi;
1315
impl<'a, 'tcx> Builder<'a, 'tcx> {
1416
/// Compile `expr`, storing the result into `destination`, which
1517
/// is assumed to be uninitialized.
18+
/// If a `drop_scope` is provided, `destination` is scheduled to be dropped
19+
/// in `scope` once it has been initialized.
1620
pub fn into_expr(
1721
&mut self,
1822
destination: &Place<'tcx>,
23+
scope: Option<region::Scope>,
1924
mut block: BasicBlock,
2025
expr: Expr<'tcx>,
2126
) -> BlockAnd<()> {
2227
debug!(
23-
"into_expr(destination={:?}, block={:?}, expr={:?})",
24-
destination, block, expr
28+
"into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})",
29+
destination, scope, block, expr
2530
);
2631

2732
// since we frequently have to reference `self` from within a
@@ -37,6 +42,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3742
_ => false,
3843
};
3944

45+
let schedule_drop = move |this: &mut Self| {
46+
if let Some(drop_scope) = scope {
47+
let local = destination.as_local()
48+
.expect("cannot schedule drop of non-Local place");
49+
this.schedule_drop(expr_span, drop_scope, local, DropKind::Value);
50+
}
51+
};
52+
4053
if !expr_is_block_or_scope {
4154
this.block_context.push(BlockFrame::SubExpr);
4255
}
@@ -49,14 +62,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4962
} => {
5063
let region_scope = (region_scope, source_info);
5164
this.in_scope(region_scope, lint_level, |this| {
52-
this.into(destination, block, value)
65+
this.into(destination, scope, block, value)
5366
})
5467
}
5568
ExprKind::Block { body: ast_block } => {
56-
this.ast_block(destination, block, ast_block, source_info)
69+
this.ast_block(destination, scope, block, ast_block, source_info)
5770
}
5871
ExprKind::Match { scrutinee, arms } => {
59-
this.match_expr(destination, expr_span, block, scrutinee, arms)
72+
this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
6073
}
6174
ExprKind::NeverToAny { source } => {
6275
let source = this.hir.mirror(source);
@@ -69,6 +82,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6982

7083
// This is an optimization. If the expression was a call then we already have an
7184
// unreachable block. Don't bother to terminate it and create a new one.
85+
schedule_drop(this);
7286
if is_call {
7387
block.unit()
7488
} else {
@@ -168,6 +182,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
168182
this.in_breakable_scope(
169183
Some(loop_block),
170184
destination.clone(),
185+
scope,
171186
expr_span,
172187
move |this| {
173188
// conduct the test, if necessary
@@ -186,12 +201,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
186201
// introduce a unit temporary as the destination for the loop body.
187202
let tmp = this.get_unit_temp();
188203
// Execute the body, branching back to the test.
189-
let body_block_end = unpack!(this.into(&tmp, body_block, body));
204+
// No scope is provided, since we've scheduled the drop above.
205+
let body_block_end = unpack!(this.into(&tmp, None, body_block, body));
190206
this.cfg.terminate(
191207
body_block_end,
192208
source_info,
193209
TerminatorKind::Goto { target: loop_block },
194210
);
211+
schedule_drop(this);
195212
None
196213
},
197214
)
@@ -234,8 +251,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
234251
is_block_tail: None,
235252
});
236253
let ptr_temp = Place::from(ptr_temp);
237-
let block = unpack!(this.into(&ptr_temp, block, ptr));
238-
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), block, val)
254+
// No need for a scope, ptr_temp doesn't need drop
255+
let block = unpack!(this.into(&ptr_temp, None, block, ptr));
256+
// Maybe we should provide a scope here so that
257+
// `move_val_init` wouldn't leak on panic even with an
258+
// arbitrary `val` expression, but `schedule_drop`,
259+
// borrowck and drop elaboration all prevent us from
260+
// dropping `ptr_temp.deref()`.
261+
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), None, block, val)
239262
} else {
240263
let args: Vec<_> = args
241264
.into_iter()
@@ -265,11 +288,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
265288
from_hir_call,
266289
},
267290
);
291+
schedule_drop(this);
268292
success.unit()
269293
}
270294
}
271295
ExprKind::Use { source } => {
272-
this.into(destination, block, source)
296+
this.into(destination, scope, block, source)
273297
}
274298
ExprKind::Borrow { arg, borrow_kind } => {
275299
// We don't do this in `as_rvalue` because we use `as_place`
@@ -364,6 +388,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
364388
destination,
365389
Rvalue::Aggregate(adt, fields)
366390
);
391+
schedule_drop(this);
367392
block.unit()
368393
}
369394

@@ -391,6 +416,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
391416
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
392417
this.cfg
393418
.push_assign(block, source_info, destination, rvalue);
419+
schedule_drop(this);
394420
block.unit()
395421
}
396422
ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => {
@@ -410,6 +436,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
410436
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
411437
this.cfg
412438
.push_assign(block, source_info, destination, rvalue);
439+
schedule_drop(this);
413440
block.unit()
414441
}
415442

@@ -440,6 +467,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
440467

441468
let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
442469
this.cfg.push_assign(block, source_info, destination, rvalue);
470+
schedule_drop(this);
443471
block.unit()
444472
}
445473
};

src/librustc_mir/build/into.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +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-
pub fn into<E>(&mut self,
22-
destination: &Place<'tcx>,
23-
block: BasicBlock,
24-
expr: E)
25-
-> BlockAnd<()>
26-
where E: EvalInto<'tcx>
23+
pub fn into<E>(
24+
&mut self,
25+
destination: &Place<'tcx>,
26+
scope: Option<region::Scope>,
27+
block: BasicBlock,
28+
expr: E,
29+
) -> BlockAnd<()>
30+
where
31+
E: EvalInto<'tcx>,
2732
{
28-
expr.eval_into(self, destination, block)
33+
expr.eval_into(self, destination, scope, block)
2934
}
3035
}
3136

@@ -34,10 +39,11 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
3439
self,
3540
builder: &mut Builder<'_, 'tcx>,
3641
destination: &Place<'tcx>,
42+
scope: Option<region::Scope>,
3743
block: BasicBlock,
3844
) -> BlockAnd<()> {
3945
let expr = builder.hir.mirror(self);
40-
builder.into_expr(destination, block, expr)
46+
builder.into_expr(destination, scope, block, expr)
4147
}
4248
}
4349

@@ -46,8 +52,9 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
4652
self,
4753
builder: &mut Builder<'_, 'tcx>,
4854
destination: &Place<'tcx>,
55+
scope: Option<region::Scope>,
4956
block: BasicBlock,
5057
) -> BlockAnd<()> {
51-
builder.into_expr(destination, block, self)
58+
builder.into_expr(destination, scope, block, self)
5259
}
5360
}

0 commit comments

Comments
 (0)