Skip to content

Commit b905bf4

Browse files
committed
Auto merge of rust-lang#125923 - matthewjasper:no-return-leak, r=<try>
Fix leaks from panics in destructors Resurrects rust-lang#78373. This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path). Closes rust-lang#47949 r? `@lcnr`
2 parents 0da95bd + 3e0db6a commit b905bf4

24 files changed

+778
-492
lines changed

compiler/rustc_mir_build/src/build/block.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::build::matches::{DeclareLetBindings, EmitStorageLive, ScheduleDrops};
2+
use crate::build::scope::DropKind;
23
use crate::build::ForGuard::OutsideGuard;
34
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
45
use rustc_middle::middle::region::Scope;
@@ -12,6 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1213
pub(crate) fn ast_block(
1314
&mut self,
1415
destination: Place<'tcx>,
16+
scope: Option<Scope>,
1517
block: BasicBlock,
1618
ast_block: BlockId,
1719
source_info: SourceInfo,
@@ -20,18 +22,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2022
self.thir[ast_block];
2123
self.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
2224
if targeted_by_break {
23-
this.in_breakable_scope(None, destination, span, |this| {
24-
Some(this.ast_block_stmts(destination, block, span, stmts, expr, region_scope))
25+
this.in_breakable_scope(None, destination, scope, span, |this| {
26+
Some(this.ast_block_stmts(
27+
destination,
28+
scope,
29+
block,
30+
span,
31+
stmts,
32+
expr,
33+
region_scope,
34+
))
2535
})
2636
} else {
27-
this.ast_block_stmts(destination, block, span, stmts, expr, region_scope)
37+
this.ast_block_stmts(destination, scope, block, span, stmts, expr, region_scope)
2838
}
2939
})
3040
}
3141

3242
fn ast_block_stmts(
3343
&mut self,
3444
destination: Place<'tcx>,
45+
scope: Option<Scope>,
3546
mut block: BasicBlock,
3647
span: Span,
3748
stmts: &[StmtId],
@@ -169,6 +180,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
169180
unpack!(
170181
failure_block = this.ast_block(
171182
dummy_place,
183+
None,
172184
failure_entry,
173185
*else_block,
174186
this.source_info(else_block_span),
@@ -333,7 +345,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
333345
this.block_context
334346
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
335347

336-
unpack!(block = this.expr_into_dest(destination, block, expr_id));
348+
unpack!(block = this.expr_into_dest(destination, scope, block, expr_id));
337349
let popped = this.block_context.pop();
338350

339351
assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
@@ -350,6 +362,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
350362
// We only want to assign an implicit `()` as the return value of the block if the
351363
// block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
352364
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
365+
} else if let Some(destination_local) = destination.as_local()
366+
&& let Some(scope) = scope
367+
{
368+
this.schedule_drop(span, scope, destination_local, DropKind::Value);
353369
}
354370
}
355371
// Finally, we pop all the let scopes before exiting out from the scope of block

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use rustc_middle::ty::{self, Ty, UpvarArgs};
2020
use rustc_span::{Span, DUMMY_SP};
2121
use tracing::debug;
2222

23+
use std::slice;
24+
2325
impl<'a, 'tcx> Builder<'a, 'tcx> {
2426
/// Returns an rvalue suitable for use until the end of the current
2527
/// scope expression.
@@ -184,15 +186,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
184186
let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value_ty);
185187
this.cfg.push_assign(block, source_info, Place::from(result), box_);
186188

187-
// initialize the box contents:
189+
// Initialize the box contents. No scope is needed since the
190+
// `Box` is already scheduled to be dropped.
188191
unpack!(
189192
block = this.expr_into_dest(
190193
this.tcx.mk_place_deref(Place::from(result)),
194+
None,
191195
block,
192196
value,
193197
)
194198
);
195-
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
199+
let result_operand = Operand::Move(Place::from(result));
200+
this.record_operands_moved(slice::from_ref(&result_operand));
201+
block.and(Rvalue::Use(result_operand))
196202
}
197203
ExprKind::Cast { source } => {
198204
let source_expr = &this.thir[source];
@@ -360,6 +366,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
360366
})
361367
.collect();
362368

369+
this.record_operands_moved(&fields.raw);
363370
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(el_ty)), fields))
364371
}
365372
ExprKind::Tuple { ref fields } => {
@@ -381,6 +388,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
381388
})
382389
.collect();
383390

391+
this.record_operands_moved(&fields.raw);
384392
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields))
385393
}
386394
ExprKind::Closure(box ClosureExpr {
@@ -483,6 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
483491
Box::new(AggregateKind::CoroutineClosure(closure_id.to_def_id(), args))
484492
}
485493
};
494+
this.record_operands_moved(&operands.raw);
486495
block.and(Rvalue::Aggregate(result, operands))
487496
}
488497
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
@@ -738,7 +747,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
738747
this.diverge_from(block);
739748
block = success;
740749
}
741-
this.record_operands_moved(&[Spanned { node: value_operand, span: DUMMY_SP }]);
750+
this.record_operands_moved(&[value_operand]);
742751
}
743752
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new()))
744753
}

compiler/rustc_mir_build/src/build/expr/as_temp.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
112112
}
113113
}
114114

115-
unpack!(block = this.expr_into_dest(temp_place, block, expr_id));
116-
117-
if let Some(temp_lifetime) = temp_lifetime {
118-
this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
119-
}
115+
unpack!(block = this.expr_into_dest(temp_place, temp_lifetime, block, expr_id));
120116

121117
block.and(temp)
122118
}

0 commit comments

Comments
 (0)