22
33use crate :: build:: expr:: category:: { Category , RvalueFunc } ;
44use crate :: build:: matches:: DeclareLetBindings ;
5+ use crate :: build:: scope:: DropKind ;
56use crate :: build:: { BlockAnd , BlockAndExtension , BlockFrame , Builder , NeedsTemporary } ;
67use rustc_ast:: InlineAsmOptions ;
78use rustc_data_structures:: fx:: FxHashMap ;
89use rustc_data_structures:: stack:: ensure_sufficient_stack;
910use rustc_hir as hir;
11+ use rustc_index:: IndexVec ;
12+ use rustc_middle:: middle:: region;
1013use rustc_middle:: mir:: * ;
1114use rustc_middle:: span_bug;
1215use rustc_middle:: thir:: * ;
@@ -15,13 +18,16 @@ use rustc_span::source_map::Spanned;
1518use std:: iter;
1619use tracing:: { debug, instrument} ;
1720
21+ use std:: slice;
22+
1823impl < ' a , ' tcx > Builder < ' a , ' tcx > {
1924 /// Compile `expr`, storing the result into `destination`, which
2025 /// is assumed to be uninitialized.
2126 #[ instrument( level = "debug" , skip( self ) ) ]
2227 pub ( crate ) fn expr_into_dest (
2328 & mut self ,
2429 destination : Place < ' tcx > ,
30+ scope : Option < region:: Scope > ,
2531 mut block : BasicBlock ,
2632 expr_id : ExprId ,
2733 ) -> BlockAnd < ( ) > {
@@ -36,6 +42,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3642 let expr_is_block_or_scope =
3743 matches ! ( expr. kind, ExprKind :: Block { .. } | ExprKind :: Scope { .. } ) ;
3844
45+ let schedule_drop = move |this : & mut Self | {
46+ if let Some ( drop_scope) = scope {
47+ let local =
48+ destination. as_local ( ) . expect ( "cannot schedule drop of non-Local place" ) ;
49+ this. schedule_drop ( expr_span, drop_scope, local, DropKind :: Value ) ;
50+ }
51+ } ;
52+
3953 if !expr_is_block_or_scope {
4054 this. block_context . push ( BlockFrame :: SubExpr ) ;
4155 }
@@ -45,15 +59,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4559 let region_scope = ( region_scope, source_info) ;
4660 ensure_sufficient_stack ( || {
4761 this. in_scope ( region_scope, lint_level, |this| {
48- this. expr_into_dest ( destination, block, value)
62+ this. expr_into_dest ( destination, scope , block, value)
4963 } )
5064 } )
5165 }
5266 ExprKind :: Block { block : ast_block } => {
53- this. ast_block ( destination, block, ast_block, source_info)
67+ this. ast_block ( destination, scope , block, ast_block, source_info)
5468 }
5569 ExprKind :: Match { scrutinee, ref arms, .. } => this. match_expr (
5670 destination,
71+ scope,
5772 block,
5873 scrutinee,
5974 arms,
@@ -91,7 +106,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
91106 ) ) ;
92107
93108 // Lower the `then` arm into its block.
94- this. expr_into_dest ( destination, then_blk, then)
109+ let then_blk =
110+ this. expr_into_dest ( destination, scope, then_blk, then) ;
111+ if let Some ( drop_scope) = scope {
112+ let local = destination
113+ . as_local ( )
114+ . expect ( "cannot unschedule drop of non-Local place" ) ;
115+ this. unschedule_drop ( drop_scope, local) ;
116+ }
117+ then_blk
95118 } ) ;
96119
97120 // Pack `(then_block, else_block)` into `BlockAnd<BasicBlock>`.
@@ -105,7 +128,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
105128
106129 // If there is an `else` arm, lower it into `else_blk`.
107130 if let Some ( else_expr) = else_opt {
108- unpack ! ( else_blk = this. expr_into_dest( destination, else_blk, else_expr) ) ;
131+ unpack ! (
132+ else_blk = this. expr_into_dest( destination, scope, else_blk, else_expr)
133+ ) ;
109134 } else {
110135 // There is no `else` arm, so we know both arms have type `()`.
111136 // Generate the implicit `else {}` by assigning unit.
@@ -140,6 +165,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
140165
141166 // This is an optimization. If the expression was a call then we already have an
142167 // unreachable block. Don't bother to terminate it and create a new one.
168+ schedule_drop ( this) ;
143169 if is_call {
144170 block. unit ( )
145171 } else {
@@ -187,7 +213,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
187213 const_ : Const :: from_bool ( this. tcx , constant) ,
188214 } ,
189215 ) ;
190- let mut rhs_block = unpack ! ( this. expr_into_dest( destination, continuation, rhs) ) ;
216+ let mut rhs_block =
217+ unpack ! ( this. expr_into_dest( destination, scope, continuation, rhs) ) ;
191218 // Instrument the lowered RHS's value for condition coverage.
192219 // (Does nothing if condition coverage is not enabled.)
193220 this. visit_coverage_standalone_condition ( rhs, destination, & mut rhs_block) ;
@@ -213,29 +240,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
213240 // Start the loop.
214241 this. cfg . goto ( block, source_info, loop_block) ;
215242
216- this. in_breakable_scope ( Some ( loop_block) , destination, expr_span, move |this| {
217- // conduct the test, if necessary
218- let body_block = this. cfg . start_new_block ( ) ;
219- this. cfg . terminate (
220- loop_block,
221- source_info,
222- TerminatorKind :: FalseUnwind {
223- real_target : body_block,
224- unwind : UnwindAction :: Continue ,
225- } ,
226- ) ;
227- this. diverge_from ( loop_block) ;
228-
229- // The “return” value of the loop body must always be a unit. We therefore
230- // introduce a unit temporary as the destination for the loop body.
231- let tmp = this. get_unit_temp ( ) ;
232- // Execute the body, branching back to the test.
233- let body_block_end = unpack ! ( this. expr_into_dest( tmp, body_block, body) ) ;
234- this. cfg . goto ( body_block_end, source_info, loop_block) ;
235-
236- // Loops are only exited by `break` expressions.
237- None
238- } )
243+ this. in_breakable_scope (
244+ Some ( loop_block) ,
245+ destination,
246+ scope,
247+ expr_span,
248+ move |this| {
249+ // conduct the test, if necessary
250+ let body_block = this. cfg . start_new_block ( ) ;
251+ this. cfg . terminate (
252+ loop_block,
253+ source_info,
254+ TerminatorKind :: FalseUnwind {
255+ real_target : body_block,
256+ unwind : UnwindAction :: Continue ,
257+ } ,
258+ ) ;
259+ this. diverge_from ( loop_block) ;
260+
261+ // The “return” value of the loop body must always be a unit. We therefore
262+ // introduce a unit temporary as the destination for the loop body.
263+ let tmp = this. get_unit_temp ( ) ;
264+ // Execute the body, branching back to the test.
265+ let body_block_end =
266+ unpack ! ( this. expr_into_dest( tmp, scope, body_block, body) ) ;
267+ this. cfg . goto ( body_block_end, source_info, loop_block) ;
268+ schedule_drop ( this) ;
269+
270+ // Loops are only exited by `break` expressions.
271+ None
272+ } ,
273+ )
239274 }
240275 ExprKind :: Call { ty : _, fun, ref args, from_hir_call, fn_span } => {
241276 let fun = unpack ! ( block = this. as_local_operand( block, fun) ) ;
@@ -284,9 +319,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
284319 // FIXME(matthewjasper): Look at this again if Polonius is
285320 // stabilized.
286321 this. record_operands_moved ( & args) ;
322+ schedule_drop ( this) ;
287323 success. unit ( )
288324 }
289- ExprKind :: Use { source } => this. expr_into_dest ( destination, block, source) ,
325+ ExprKind :: Use { source } => this. expr_into_dest ( destination, scope , block, source) ,
290326 ExprKind :: Borrow { arg, borrow_kind } => {
291327 // We don't do this in `as_rvalue` because we use `as_place`
292328 // for borrow expressions, so we cannot create an `RValue` that
@@ -349,7 +385,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
349385
350386 let field_names = adt_def. variant ( variant_index) . fields . indices ( ) ;
351387
352- let fields = if let Some ( FruInfo { base, field_types } ) = base {
388+ let fields: IndexVec < _ , _ > = if let Some ( FruInfo { base, field_types } ) = base {
353389 let place_builder = unpack ! ( block = this. as_place_builder( block, * base) ) ;
354390
355391 // MIR does not natively support FRU, so for each
@@ -390,6 +426,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
390426 destination,
391427 Rvalue :: Aggregate ( adt, fields) ,
392428 ) ;
429+ schedule_drop ( this) ;
393430 block. unit ( )
394431 }
395432 ExprKind :: InlineAsm ( box InlineAsmExpr {
@@ -468,7 +505,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
468505 targets. push ( target) ;
469506
470507 let tmp = this. get_unit_temp ( ) ;
471- let target = unpack ! ( this. ast_block( tmp, target, block, source_info) ) ;
508+ let target =
509+ unpack ! ( this. ast_block( tmp, scope, target, block, source_info) ) ;
472510 this. cfg . terminate (
473511 target,
474512 source_info,
@@ -532,6 +570,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
532570 let place = unpack ! ( block = this. as_place( block, expr_id) ) ;
533571 let rvalue = Rvalue :: Use ( this. consume_by_copy_or_move ( place) ) ;
534572 this. cfg . push_assign ( block, source_info, destination, rvalue) ;
573+ schedule_drop ( this) ;
535574 block. unit ( )
536575 }
537576 ExprKind :: Index { .. } | ExprKind :: Deref { .. } | ExprKind :: Field { .. } => {
@@ -547,6 +586,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
547586 let place = unpack ! ( block = this. as_place( block, expr_id) ) ;
548587 let rvalue = Rvalue :: Use ( this. consume_by_copy_or_move ( place) ) ;
549588 this. cfg . push_assign ( block, source_info, destination, rvalue) ;
589+ schedule_drop ( this) ;
550590 block. unit ( )
551591 }
552592
@@ -569,6 +609,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
569609 TerminatorKind :: Yield { value, resume, resume_arg : destination, drop : None } ,
570610 ) ;
571611 this. coroutine_drop_cleanup ( block) ;
612+ schedule_drop ( this) ;
572613 resume. unit ( )
573614 }
574615
@@ -605,6 +646,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
605646
606647 let rvalue = unpack ! ( block = this. as_local_rvalue( block, expr_id) ) ;
607648 this. cfg . push_assign ( block, source_info, destination, rvalue) ;
649+ schedule_drop ( this) ;
608650 block. unit ( )
609651 }
610652 } ;
0 commit comments