1
Fork 0

Reuse lower_let_expr for let .. else lowering

This commit is contained in:
Nadrieril 2024-06-17 20:51:35 +02:00
parent 7b150a161e
commit ff49c3769b
2 changed files with 49 additions and 87 deletions

View file

@ -189,38 +189,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let initializer_span = this.thir[*initializer].span; let initializer_span = this.thir[*initializer].span;
let scope = (*init_scope, source_info); let scope = (*init_scope, source_info);
let failure = unpack!( let failure_and_block = this.in_scope(scope, *lint_level, |this| {
block = this.in_scope(scope, *lint_level, |this| { this.declare_bindings(
this.declare_bindings( visibility_scope,
visibility_scope, remainder_span,
remainder_span, pattern,
pattern, None,
None, Some((Some(&destination), initializer_span)),
Some((Some(&destination), initializer_span)), );
); this.visit_primary_bindings(
this.visit_primary_bindings( 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, let else_block_span = this.thir[*else_block].span;
span, let (matching, failure) =
OutsideGuard, this.in_if_then_scope(last_remainder_scope, else_block_span, |this| {
true, this.lower_let_expr(
); block,
}, *initializer,
); pattern,
this.ast_let_else( None,
block, initializer_span,
*initializer, false,
initializer_span, true,
*else_block, )
&last_remainder_scope, });
pattern, matching.and(failure)
) });
}) let failure = unpack!(block = failure_and_block);
);
this.cfg.goto(failure, source_info, failure_entry); this.cfg.goto(failure, source_info, failure_entry);
if let Some(source_scope) = visibility_scope { if let Some(source_scope) = visibility_scope {

View file

@ -147,6 +147,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some(args.variable_source_info.scope), Some(args.variable_source_info.scope),
args.variable_source_info.span, args.variable_source_info.span,
args.declare_let_bindings, args.declare_let_bindings,
false,
), ),
_ => { _ => {
let mut block = block; let mut block = block;
@ -1981,48 +1982,50 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'a, 'tcx> Builder<'a, 'tcx> {
/// If the bindings have already been declared, set `declare_bindings` to /// If the bindings have already been declared, set `declare_bindings` to
/// `false` to avoid duplicated bindings declaration. Used for if-let guards. /// `false` to avoid duplicated bindings declaration; used for if-let guards.
pub(crate) fn lower_let_expr( pub(crate) fn lower_let_expr(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr_id: ExprId, expr_id: ExprId,
pat: &Pat<'tcx>, pat: &Pat<'tcx>,
source_scope: Option<SourceScope>, source_scope: Option<SourceScope>,
span: Span, scope_span: Span,
declare_bindings: bool, declare_bindings: bool,
storages_alive: bool,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
let expr_span = self.thir[expr_id].span; let expr_span = self.thir[expr_id].span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span)); let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self); let mut candidate = Candidate::new(scrutinee.clone(), pat, false, self);
let otherwise_block = self.lower_match_tree( let otherwise_block = self.lower_match_tree(
block, block,
expr_span,
&scrutinee,
pat.span, pat.span,
&expr_place_builder, &mut [&mut candidate],
pat.span,
&mut [&mut guard_candidate],
true, true,
); );
let expr_place = expr_place_builder.try_to_place(self);
let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
self.break_for_else(otherwise_block, self.source_info(expr_span)); self.break_for_else(otherwise_block, self.source_info(expr_span));
if declare_bindings { if declare_bindings {
self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place); let expr_place = scrutinee.try_to_place(self);
let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
self.declare_bindings(source_scope, pat.span.to(scope_span), pat, None, opt_expr_place);
} }
let post_guard_block = self.bind_pattern( let success = self.bind_pattern(
self.source_info(pat.span), self.source_info(pat.span),
guard_candidate, candidate,
&[], &[],
expr_span, expr_span,
None, None,
false, storages_alive,
); );
// If branch coverage is enabled, record this branch. // If branch coverage is enabled, record this branch.
self.visit_coverage_conditional_let(pat, post_guard_block, otherwise_block); self.visit_coverage_conditional_let(pat, success, otherwise_block);
post_guard_block.unit() success.unit()
} }
/// Initializes each of the bindings from the candidate by /// Initializes each of the bindings from the candidate by
@ -2469,44 +2472,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!(?locals); debug!(?locals);
self.var_indices.insert(var_id, locals); self.var_indices.insert(var_id, locals);
} }
pub(crate) fn ast_let_else(
&mut self,
mut block: BasicBlock,
init_id: ExprId,
initializer_span: Span,
else_block: BlockId,
let_else_scope: &region::Scope,
pattern: &Pat<'tcx>,
) -> BlockAnd<BasicBlock> {
let else_block_span = self.thir[else_block].span;
let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init_id, initializer_span));
let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
let failure_block = this.lower_match_tree(
block,
initializer_span,
&scrutinee,
pattern.span,
&mut [&mut candidate],
true,
);
// This block is for the matching case
let matching = this.bind_pattern(
this.source_info(pattern.span),
candidate,
&[],
initializer_span,
None,
true,
);
// If branch coverage is enabled, record this branch.
this.visit_coverage_conditional_let(pattern, matching, failure_block);
this.break_for_else(failure_block, this.source_info(initializer_span));
matching.unit()
});
matching.and(failure)
}
} }