Replace a magic boolean with enum ScheduleDrops
This commit is contained in:
parent
3b22589cfa
commit
ed07712e96
2 changed files with 56 additions and 18 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::build::matches::{DeclareLetBindings, EmitStorageLive};
|
use crate::build::matches::{DeclareLetBindings, EmitStorageLive, ScheduleDrops};
|
||||||
use crate::build::ForGuard::OutsideGuard;
|
use crate::build::ForGuard::OutsideGuard;
|
||||||
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
||||||
use rustc_middle::middle::region::Scope;
|
use rustc_middle::middle::region::Scope;
|
||||||
|
@ -202,7 +202,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
pattern,
|
pattern,
|
||||||
UserTypeProjections::none(),
|
UserTypeProjections::none(),
|
||||||
&mut |this, _, _, node, span, _, _| {
|
&mut |this, _, _, node, span, _, _| {
|
||||||
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
this.storage_live_binding(
|
||||||
|
block,
|
||||||
|
node,
|
||||||
|
span,
|
||||||
|
OutsideGuard,
|
||||||
|
ScheduleDrops::Yes,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let else_block_span = this.thir[*else_block].span;
|
let else_block_span = this.thir[*else_block].span;
|
||||||
|
@ -292,7 +298,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
pattern,
|
pattern,
|
||||||
UserTypeProjections::none(),
|
UserTypeProjections::none(),
|
||||||
&mut |this, _, _, node, span, _, _| {
|
&mut |this, _, _, node, span, _, _| {
|
||||||
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
this.storage_live_binding(
|
||||||
|
block,
|
||||||
|
node,
|
||||||
|
span,
|
||||||
|
OutsideGuard,
|
||||||
|
ScheduleDrops::Yes,
|
||||||
|
);
|
||||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,7 @@ mod simplify;
|
||||||
mod test;
|
mod test;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use std::assert_matches::assert_matches;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -74,6 +75,17 @@ pub(crate) enum EmitStorageLive {
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by [`Builder::storage_live_binding`] and [`Builder::bind_matched_candidate_for_arm_body`]
|
||||||
|
/// to decide whether to schedule drops.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) enum ScheduleDrops {
|
||||||
|
/// Yes, the relevant functions should also schedule drops as appropriate.
|
||||||
|
Yes,
|
||||||
|
/// No, don't schedule drops. The caller has taken responsibility for any
|
||||||
|
/// appropriate drops.
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Lowers a condition in a way that ensures that variables bound in any let
|
/// Lowers a condition in a way that ensures that variables bound in any let
|
||||||
/// expressions are definitely initialized in the if body.
|
/// expressions are definitely initialized in the if body.
|
||||||
|
@ -535,7 +547,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fake_borrow_temps,
|
fake_borrow_temps,
|
||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
arm_match_scope,
|
arm_match_scope,
|
||||||
true,
|
ScheduleDrops::Yes,
|
||||||
emit_storage_live,
|
emit_storage_live,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -554,7 +566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// To handle this we instead unschedule it's drop after each time
|
// To handle this we instead unschedule it's drop after each time
|
||||||
// we lower the guard.
|
// we lower the guard.
|
||||||
let target_block = self.cfg.start_new_block();
|
let target_block = self.cfg.start_new_block();
|
||||||
let mut schedule_drops = true;
|
let mut schedule_drops = ScheduleDrops::Yes;
|
||||||
let arm = arm_match_scope.unzip().0;
|
let arm = arm_match_scope.unzip().0;
|
||||||
// We keep a stack of all of the bindings and type ascriptions
|
// We keep a stack of all of the bindings and type ascriptions
|
||||||
// from the parent candidates that we visit, that also need to
|
// from the parent candidates that we visit, that also need to
|
||||||
|
@ -576,7 +588,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
emit_storage_live,
|
emit_storage_live,
|
||||||
);
|
);
|
||||||
if arm.is_none() {
|
if arm.is_none() {
|
||||||
schedule_drops = false;
|
schedule_drops = ScheduleDrops::No;
|
||||||
}
|
}
|
||||||
self.cfg.goto(binding_end, outer_source_info, target_block);
|
self.cfg.goto(binding_end, outer_source_info, target_block);
|
||||||
},
|
},
|
||||||
|
@ -602,8 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
match irrefutable_pat.kind {
|
match irrefutable_pat.kind {
|
||||||
// Optimize the case of `let x = ...` to write directly into `x`
|
// Optimize the case of `let x = ...` to write directly into `x`
|
||||||
PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => {
|
PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => {
|
||||||
let place =
|
let place = self.storage_live_binding(
|
||||||
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
|
block,
|
||||||
|
var,
|
||||||
|
irrefutable_pat.span,
|
||||||
|
OutsideGuard,
|
||||||
|
ScheduleDrops::Yes,
|
||||||
|
);
|
||||||
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
||||||
|
|
||||||
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
||||||
|
@ -636,8 +653,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
},
|
},
|
||||||
ascription: thir::Ascription { ref annotation, variance: _ },
|
ascription: thir::Ascription { ref annotation, variance: _ },
|
||||||
} => {
|
} => {
|
||||||
let place =
|
let place = self.storage_live_binding(
|
||||||
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
|
block,
|
||||||
|
var,
|
||||||
|
irrefutable_pat.span,
|
||||||
|
OutsideGuard,
|
||||||
|
ScheduleDrops::Yes,
|
||||||
|
);
|
||||||
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
||||||
|
|
||||||
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
||||||
|
@ -827,7 +849,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
var: LocalVarId,
|
var: LocalVarId,
|
||||||
span: Span,
|
span: Span,
|
||||||
for_guard: ForGuard,
|
for_guard: ForGuard,
|
||||||
schedule_drop: bool,
|
schedule_drop: ScheduleDrops,
|
||||||
) -> Place<'tcx> {
|
) -> Place<'tcx> {
|
||||||
let local_id = self.var_local_id(var, for_guard);
|
let local_id = self.var_local_id(var, for_guard);
|
||||||
let source_info = self.source_info(span);
|
let source_info = self.source_info(span);
|
||||||
|
@ -835,7 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Although there is almost always scope for given variable in corner cases
|
// Although there is almost always scope for given variable in corner cases
|
||||||
// like #92893 we might get variable with no scope.
|
// like #92893 we might get variable with no scope.
|
||||||
if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id)
|
if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id)
|
||||||
&& schedule_drop
|
&& matches!(schedule_drop, ScheduleDrops::Yes)
|
||||||
{
|
{
|
||||||
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
|
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
|
||||||
}
|
}
|
||||||
|
@ -2112,7 +2134,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
|
fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
|
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
|
||||||
schedule_drops: bool,
|
schedule_drops: ScheduleDrops,
|
||||||
emit_storage_live: EmitStorageLive,
|
emit_storage_live: EmitStorageLive,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
||||||
|
@ -2323,10 +2345,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let cause = FakeReadCause::ForGuardBinding;
|
let cause = FakeReadCause::ForGuardBinding;
|
||||||
self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id));
|
self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id));
|
||||||
}
|
}
|
||||||
assert!(schedule_drops, "patterns with guards must schedule drops");
|
assert_matches!(
|
||||||
|
schedule_drops,
|
||||||
|
ScheduleDrops::Yes,
|
||||||
|
"patterns with guards must schedule drops"
|
||||||
|
);
|
||||||
self.bind_matched_candidate_for_arm_body(
|
self.bind_matched_candidate_for_arm_body(
|
||||||
post_guard_block,
|
post_guard_block,
|
||||||
true,
|
ScheduleDrops::Yes,
|
||||||
by_value_bindings,
|
by_value_bindings,
|
||||||
emit_storage_live,
|
emit_storage_live,
|
||||||
);
|
);
|
||||||
|
@ -2376,7 +2402,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn bind_matched_candidate_for_guard<'b>(
|
fn bind_matched_candidate_for_guard<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
schedule_drops: bool,
|
schedule_drops: ScheduleDrops,
|
||||||
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
||||||
) where
|
) where
|
||||||
'tcx: 'b,
|
'tcx: 'b,
|
||||||
|
@ -2429,7 +2455,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn bind_matched_candidate_for_arm_body<'b>(
|
fn bind_matched_candidate_for_arm_body<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
schedule_drops: bool,
|
schedule_drops: ScheduleDrops,
|
||||||
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
||||||
emit_storage_live: EmitStorageLive,
|
emit_storage_live: EmitStorageLive,
|
||||||
) where
|
) where
|
||||||
|
@ -2454,7 +2480,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
schedule_drops,
|
schedule_drops,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
if schedule_drops {
|
if matches!(schedule_drops, ScheduleDrops::Yes) {
|
||||||
self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
|
self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
|
||||||
}
|
}
|
||||||
let rvalue = match binding.binding_mode.0 {
|
let rvalue = match binding.binding_mode.0 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue