avoid duplicating StorageLive in let-else
This commit is contained in:
parent
bc7b17cfe3
commit
48c1c1d190
2 changed files with 33 additions and 9 deletions
|
@ -232,7 +232,8 @@ 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, false);
|
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
||||||
|
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let failure = unpack!(
|
let failure = unpack!(
|
||||||
|
|
|
@ -371,6 +371,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
Some(arm.span),
|
Some(arm.span),
|
||||||
Some(arm.scope),
|
Some(arm.scope),
|
||||||
Some(match_scope),
|
Some(match_scope),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(source_scope) = scope {
|
if let Some(source_scope) = scope {
|
||||||
|
@ -416,6 +417,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm_span: Option<Span>,
|
arm_span: Option<Span>,
|
||||||
arm_scope: Option<region::Scope>,
|
arm_scope: Option<region::Scope>,
|
||||||
match_scope: Option<region::Scope>,
|
match_scope: Option<region::Scope>,
|
||||||
|
storages_alive: bool,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
if candidate.subcandidates.is_empty() {
|
if candidate.subcandidates.is_empty() {
|
||||||
// Avoid generating another `BasicBlock` when we only have one
|
// Avoid generating another `BasicBlock` when we only have one
|
||||||
|
@ -429,6 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm_span,
|
arm_span,
|
||||||
match_scope,
|
match_scope,
|
||||||
true,
|
true,
|
||||||
|
storages_alive,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// It's helpful to avoid scheduling drops multiple times to save
|
// It's helpful to avoid scheduling drops multiple times to save
|
||||||
|
@ -466,6 +469,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm_span,
|
arm_span,
|
||||||
match_scope,
|
match_scope,
|
||||||
schedule_drops,
|
schedule_drops,
|
||||||
|
storages_alive,
|
||||||
);
|
);
|
||||||
if arm_scope.is_none() {
|
if arm_scope.is_none() {
|
||||||
schedule_drops = false;
|
schedule_drops = false;
|
||||||
|
@ -641,6 +645,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unit()
|
.unit()
|
||||||
}
|
}
|
||||||
|
@ -1813,6 +1818,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
post_guard_block.unit()
|
post_guard_block.unit()
|
||||||
|
@ -1836,6 +1842,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm_span: Option<Span>,
|
arm_span: Option<Span>,
|
||||||
match_scope: Option<region::Scope>,
|
match_scope: Option<region::Scope>,
|
||||||
schedule_drops: bool,
|
schedule_drops: bool,
|
||||||
|
storages_alive: bool,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
||||||
|
|
||||||
|
@ -2051,7 +2058,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
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!(schedule_drops, "patterns with guards must schedule drops");
|
||||||
self.bind_matched_candidate_for_arm_body(post_guard_block, true, by_value_bindings);
|
self.bind_matched_candidate_for_arm_body(
|
||||||
|
post_guard_block,
|
||||||
|
true,
|
||||||
|
by_value_bindings,
|
||||||
|
storages_alive,
|
||||||
|
);
|
||||||
|
|
||||||
post_guard_block
|
post_guard_block
|
||||||
} else {
|
} else {
|
||||||
|
@ -2065,6 +2077,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(bindings, _)| bindings)
|
.flat_map(|(bindings, _)| bindings)
|
||||||
.chain(&candidate.bindings),
|
.chain(&candidate.bindings),
|
||||||
|
storages_alive,
|
||||||
);
|
);
|
||||||
block
|
block
|
||||||
}
|
}
|
||||||
|
@ -2154,6 +2167,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
schedule_drops: bool,
|
schedule_drops: bool,
|
||||||
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
|
||||||
|
storages_alive: bool,
|
||||||
) where
|
) where
|
||||||
'tcx: 'b,
|
'tcx: 'b,
|
||||||
{
|
{
|
||||||
|
@ -2163,13 +2177,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Assign each of the bindings. This may trigger moves out of the candidate.
|
// Assign each of the bindings. This may trigger moves out of the candidate.
|
||||||
for binding in bindings {
|
for binding in bindings {
|
||||||
let source_info = self.source_info(binding.span);
|
let source_info = self.source_info(binding.span);
|
||||||
let local = self.storage_live_binding(
|
let local = if storages_alive {
|
||||||
|
// Here storages are already alive, probably because this is a binding
|
||||||
|
// from let-else.
|
||||||
|
// We just need to schedule drop for the value.
|
||||||
|
self.var_local_id(binding.var_id, OutsideGuard).into()
|
||||||
|
} else {
|
||||||
|
self.storage_live_binding(
|
||||||
block,
|
block,
|
||||||
binding.var_id,
|
binding.var_id,
|
||||||
binding.span,
|
binding.span,
|
||||||
OutsideGuard,
|
OutsideGuard,
|
||||||
schedule_drops,
|
schedule_drops,
|
||||||
);
|
)
|
||||||
|
};
|
||||||
if schedule_drops {
|
if schedule_drops {
|
||||||
self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
|
self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
|
||||||
}
|
}
|
||||||
|
@ -2300,6 +2321,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
// This block is for the failure case
|
// This block is for the failure case
|
||||||
let failure = this.bind_pattern(
|
let failure = this.bind_pattern(
|
||||||
|
@ -2311,6 +2333,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
|
this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
|
||||||
matching.unit()
|
matching.unit()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue