break_scope,
Some(variable_source_info.scope),
variable_source_info.span,
+ true,
),
_ => {
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
let scrutinee_place =
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
- let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
+ let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms);
let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
let mut candidates =
/// Create the initial `Candidate`s for a `match` expression.
fn create_match_candidates<'pat>(
&mut self,
- scrutinee: PlaceBuilder<'tcx>,
+ scrutinee: &PlaceBuilder<'tcx>,
arms: &'pat [ArmId],
) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
where
None,
arm.span,
&arm.pattern,
- ArmHasGuard(arm.guard.is_some()),
+ arm.guard.as_ref(),
opt_scrutinee_place,
);
mut visibility_scope: Option<SourceScope>,
scope_span: Span,
pattern: &Pat<'tcx>,
- has_guard: ArmHasGuard,
+ guard: Option<&Guard<'tcx>>,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
self.visit_primary_bindings(
var,
ty,
user_ty,
- has_guard,
+ ArmHasGuard(guard.is_some()),
opt_match_place.map(|(x, y)| (x.cloned(), y)),
pattern.span,
);
},
);
+ if let Some(Guard::IfLet(guard_pat, _)) = guard {
+ // FIXME: pass a proper `opt_match_place`
+ self.declare_bindings(visibility_scope, scope_span, guard_pat, None, None);
+ }
visibility_scope
}
bug!("Or-patterns should have been sorted to the end");
};
let or_span = match_pair.pattern.span;
- let place = match_pair.place;
first_candidate.visit_leaves(|leaf_candidate| {
self.test_or_pattern(
&mut otherwise,
pats,
or_span,
- place.clone(),
+ &match_pair.place,
fake_borrows,
);
});
otherwise: &mut Option<BasicBlock>,
pats: &'pat [Box<Pat<'tcx>>],
or_span: Span,
- place: PlaceBuilder<'tcx>,
+ place: &PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) {
debug!("candidate={:#?}\npats={:#?}", candidate, pats);
// encounter a candidate where the test is not relevant; at
// that point, we stop sorting.
while let Some(candidate) = candidates.first_mut() {
- let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) else {
+ let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else {
break;
};
let (candidate, rest) = candidates.split_first_mut().unwrap();
target_blocks
};
- self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks);
+ self.perform_test(span, scrutinee_span, block, &match_place, &test, make_target_blocks);
}
/// Determine the fake borrows that are needed from a set of places that
// Pat binding - used for `let` and function parameters as well.
impl<'a, 'tcx> Builder<'a, 'tcx> {
+ /// If the bindings have already been declared, set `declare_bindings` to
+ /// `false` to avoid duplicated bindings declaration. Used for if-let guards.
pub(crate) fn lower_let_expr(
&mut self,
mut block: BasicBlock,
else_target: region::Scope,
source_scope: Option<SourceScope>,
span: Span,
+ declare_bindings: bool,
) -> BlockAnd<()> {
let expr_span = expr.span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
- self.declare_bindings(
- source_scope,
- pat.span.to(span),
- pat,
- ArmHasGuard(false),
- opt_expr_place,
- );
+ if declare_bindings {
+ self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
+ }
let post_guard_block = self.bind_pattern(
self.source_info(pat.span),
Guard::IfLet(ref pat, scrutinee) => {
let s = &this.thir[scrutinee];
guard_span = s.span;
- this.lower_let_expr(block, s, pat, match_scope, None, arm.span)
+ this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
}
});