Introduce if-let guards in the HIR

This commit is contained in:
LeSeulArtichaut 2020-10-24 21:13:54 +02:00
parent a68864b688
commit 77d80b22f1
6 changed files with 24 additions and 15 deletions

View File

@ -505,14 +505,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
let pat = self.lower_pat(&arm.pat);
let guard = arm.guard.as_ref().map(|cond| {
if let ExprKind::Let(ref pat, ref scrutinee) = cond.kind {
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
} else {
hir::Guard::If(self.lower_expr(cond))
}
});
hir::Arm { hir::Arm {
hir_id: self.next_id(), hir_id: self.next_id(),
attrs: self.lower_attrs(&arm.attrs), attrs: self.lower_attrs(&arm.attrs),
pat: self.lower_pat(&arm.pat), pat,
guard: match arm.guard { guard,
Some(ref x) => Some(hir::Guard::If(self.lower_expr(x))),
_ => None,
},
body: self.lower_expr(&arm.body), body: self.lower_expr(&arm.body),
span: arm.span, span: arm.span,
} }

View File

@ -1160,6 +1160,7 @@ pub struct Arm<'hir> {
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub enum Guard<'hir> { pub enum Guard<'hir> {
If(&'hir Expr<'hir>), If(&'hir Expr<'hir>),
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
} }
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]

View File

@ -1228,6 +1228,10 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
if let Some(ref g) = arm.guard { if let Some(ref g) = arm.guard {
match g { match g {
Guard::If(ref e) => visitor.visit_expr(e), Guard::If(ref e) => visitor.visit_expr(e),
Guard::IfLet(ref pat, ref e) => {
visitor.visit_pat(pat);
visitor.visit_expr(e);
}
} }
} }
visitor.visit_expr(&arm.body); visitor.visit_expr(&arm.body);

View File

@ -2002,6 +2002,15 @@ impl<'a> State<'a> {
self.print_expr(&e); self.print_expr(&e);
self.s.space(); self.s.space();
} }
hir::Guard::IfLet(pat, e) => {
self.word_nbsp("if");
self.word_nbsp("let");
self.print_pat(&pat);
self.s.space();
self.word_space("=");
self.print_expr(&e);
self.s.space();
}
} }
} }
self.word_space("=>"); self.word_space("=>");

View File

@ -6,7 +6,6 @@ fn _if_let_guard() {
match () { match () {
() if let 0 = 1 => {} () if let 0 = 1 => {}
//~^ ERROR `if let` guard is not implemented //~^ ERROR `if let` guard is not implemented
//~| ERROR `let` expressions are not supported here
() if (let 0 = 1) => {} () if (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are experimental //~^ ERROR `let` expressions in this position are experimental

View File

@ -169,15 +169,6 @@ LL | use_expr!((let 0 = 1));
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable = help: add `#![feature(let_chains)]` to the crate attributes to enable
error: `let` expressions are not supported here
--> $DIR/feature-gate.rs:7:15
|
LL | () if let 0 = 1 => {}
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if`- and `while`-expressions
= note: as well as when nested within `&&` and parenthesis in those conditions
error: `let` expressions are not supported here error: `let` expressions are not supported here
--> $DIR/feature-gate.rs:11:16 --> $DIR/feature-gate.rs:11:16
| |