Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f9cc626

Browse files
Implement typechecking if-let guards
1 parent 77d80b2 commit f9cc626

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

compiler/rustc_typeck/src/check/_match.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4343
// FIXME(60707): Consider removing hack with principled solution.
4444
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
4545
} else {
46-
self.demand_scrutinee_type(arms, scrut)
46+
self.demand_scrutinee_type(scrut, arms_contain_ref_bindings(arms), arms.is_empty())
4747
};
4848

4949
// If there are no arms, that is a diverging match; a special case.
@@ -98,7 +98,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9898
self.diverges.set(Diverges::Maybe);
9999
match g {
100100
hir::Guard::If(e) => {
101-
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {})
101+
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
102+
}
103+
hir::Guard::IfLet(pat, e) => {
104+
let scrutinee_ty = self.demand_scrutinee_type(
105+
e,
106+
pat.contains_explicit_ref_binding(),
107+
false,
108+
);
109+
self.check_pat_top(&pat, scrutinee_ty, None, true);
102110
}
103111
};
104112
}
@@ -450,8 +458,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
450458

451459
fn demand_scrutinee_type(
452460
&self,
453-
arms: &'tcx [hir::Arm<'tcx>],
454461
scrut: &'tcx hir::Expr<'tcx>,
462+
contains_ref_bindings: Option<hir::Mutability>,
463+
no_arms: bool,
455464
) -> Ty<'tcx> {
456465
// Not entirely obvious: if matches may create ref bindings, we want to
457466
// use the *precise* type of the scrutinee, *not* some supertype, as
@@ -505,17 +514,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
505514
// (once introduced) is populated by the time we get here.
506515
//
507516
// See #44848.
508-
let contains_ref_bindings = arms
509-
.iter()
510-
.filter_map(|a| a.pat.contains_explicit_ref_binding())
511-
.max_by_key(|m| match *m {
512-
hir::Mutability::Mut => 1,
513-
hir::Mutability::Not => 0,
514-
});
515-
516517
if let Some(m) = contains_ref_bindings {
517518
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
518-
} else if arms.is_empty() {
519+
} else if no_arms {
519520
self.check_expr(scrut)
520521
} else {
521522
// ...but otherwise we want to use any supertype of the
@@ -546,3 +547,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
546547
}
547548
}
548549
}
550+
551+
fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
552+
arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m {
553+
hir::Mutability::Mut => 1,
554+
hir::Mutability::Not => 0,
555+
})
556+
}

compiler/rustc_typeck/src/check/generator_interior.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
246246
Guard::If(ref e) => {
247247
self.visit_expr(e);
248248
}
249+
Guard::IfLet(ref pat, ref e) => {
250+
self.visit_pat(pat);
251+
self.visit_expr(e);
252+
}
249253
}
250254

251255
let mut scope_var_ids =

0 commit comments

Comments
 (0)