1
Fork 0

Rollup merge of #79051 - LeSeulArtichaut:if-let-guard, r=matthewjasper

Implement if-let match guards

Implements rust-lang/rfcs#2294 (tracking issue: #51114).

I probably should do a few more things before this can be merged:
- [x] Add tests (added basic tests, more advanced tests could be done in the future?)
- [x] Add lint for exhaustive if-let guard (comparable to normal if-let statements)
- [x] Fix clippy

However since this is a nightly feature maybe it's fine to land this and do those steps in follow-up PRs.

Thanks a lot `@matthewjasper` ❤️ for helping me with lowering to MIR! Would you be interested in reviewing this?
r? `@ghost` for now
This commit is contained in:
Yuki Okushi 2020-12-17 11:43:55 +09:00 committed by GitHub
commit 1e1ba7c936
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 360 additions and 81 deletions

View file

@ -45,6 +45,8 @@ impl NonConstExpr {
return None;
}
Self::Match(IfLetGuardDesugar) => bug!("if-let guard outside a `match` expression"),
// All other expressions are allowed.
Self::Loop(Loop | While | WhileLet)
| Self::Match(

View file

@ -360,6 +360,9 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
self.add_from_pat(&arm.pat);
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
self.add_from_pat(pat);
}
intravisit::walk_arm(self, arm);
}
@ -866,10 +869,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
for arm in arms {
let body_succ = self.propagate_through_expr(&arm.body, succ);
let guard_succ = self.propagate_through_opt_expr(
arm.guard.as_ref().map(|hir::Guard::If(e)| *e),
body_succ,
);
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
hir::Guard::IfLet(pat, e) => {
let let_bind = self.define_bindings_in_pat(pat, body_succ);
self.propagate_through_expr(e, let_bind)
}
});
let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
self.merge_from_succ(ln, arm_succ);
}