Skip to content

Commit 3da6cf5

Browse files
committed
if-let: Add support for multiple patterns
This commit adds support for multiple patterns in if-let statements: ```rust let x = Some(0); if let Some(0) | Some(1) = x { println!("Got 0 or 1"); } ```
1 parent 6e055c3 commit 3da6cf5

File tree

6 files changed

+31
-16
lines changed

6 files changed

+31
-16
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ pub enum Expr_ {
732732
ExprLit(P<Lit>),
733733
ExprCast(P<Expr>, P<Ty>),
734734
ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
735-
ExprIfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>),
735+
ExprIfLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<P<Expr>>),
736736
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
737737
ExprWhile(P<Expr>, P<Block>, Option<Ident>),
738738
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.

src/libsyntax/ext/expand.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
127127
}
128128

129129
// Desugar ExprIfLet
130-
// From: `if let <pat> = <expr> <body> [<elseopt>]`
131-
ast::ExprIfLet(pat, expr, body, mut elseopt) => {
130+
// From: `if let <pats> = <expr> <body> [<elseopt>]`
131+
ast::ExprIfLet(pats, expr, body, mut elseopt) => {
132132
// to:
133133
//
134134
// match <expr> {
@@ -140,7 +140,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
140140
// `<pat> => <body>`
141141
let pat_arm = {
142142
let body_expr = fld.cx.expr_block(body);
143-
fld.cx.arm(pat.span, vec![pat], body_expr)
143+
fld.cx.arm(span, pats, body_expr)
144144
};
145145

146146
// `[_ if <elseopt_if_cond> => <elseopt_if_body>,]`

src/libsyntax/fold.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,8 +1288,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
12881288
folder.fold_block(tr),
12891289
fl.map(|x| folder.fold_expr(x)))
12901290
}
1291-
ExprIfLet(pat, expr, tr, fl) => {
1292-
ExprIfLet(folder.fold_pat(pat),
1291+
ExprIfLet(pats, expr, tr, fl) => {
1292+
ExprIfLet(pats.move_map(|x| folder.fold_pat(x)),
12931293
folder.fold_expr(expr),
12941294
folder.fold_block(tr),
12951295
fl.map(|x| folder.fold_expr(x)))

src/libsyntax/parse/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,7 +3065,7 @@ impl<'a> Parser<'a> {
30653065
pub fn parse_if_let_expr(&mut self) -> P<Expr> {
30663066
let lo = self.last_span.lo;
30673067
self.expect_keyword(keywords::Let);
3068-
let pat = self.parse_pat();
3068+
let pats = self.parse_pats();
30693069
self.expect(&token::Eq);
30703070
let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL);
30713071
let thn = self.parse_block();
@@ -3075,7 +3075,7 @@ impl<'a> Parser<'a> {
30753075
} else {
30763076
(thn.span.hi, None)
30773077
};
3078-
self.mk_expr(lo, hi, ExprIfLet(pat, expr, thn, els))
3078+
self.mk_expr(lo, hi, ExprIfLet(pats, expr, thn, els))
30793079
}
30803080

30813081
// `|args| expr`

src/libsyntax/print/pprust.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,11 +1459,11 @@ impl<'a> State<'a> {
14591459
self.print_else(e.as_ref().map(|e| &**e))
14601460
}
14611461
// "another else-if-let"
1462-
ast::ExprIfLet(ref pat, ref expr, ref then, ref e) => {
1462+
ast::ExprIfLet(ref pats, ref expr, ref then, ref e) => {
14631463
try!(self.cbox(indent_unit - 1));
14641464
try!(self.ibox(0));
14651465
try!(word(&mut self.s, " else if let "));
1466-
try!(self.print_pat(&**pat));
1466+
try!(self.print_pats(pats));
14671467
try!(space(&mut self.s));
14681468
try!(self.word_space("="));
14691469
try!(self.print_expr(&**expr));
@@ -1497,10 +1497,10 @@ impl<'a> State<'a> {
14971497
self.print_else(elseopt)
14981498
}
14991499

1500-
pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block,
1500+
pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast::Block,
15011501
elseopt: Option<&ast::Expr>) -> IoResult<()> {
15021502
try!(self.head("if let"));
1503-
try!(self.print_pat(pat));
1503+
try!(self.print_pats(pats));
15041504
try!(space(&mut self.s));
15051505
try!(self.word_space("="));
15061506
try!(self.print_expr(expr));
@@ -1721,8 +1721,8 @@ impl<'a> State<'a> {
17211721
ast::ExprIf(ref test, ref blk, ref elseopt) => {
17221722
try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
17231723
}
1724-
ast::ExprIfLet(ref pat, ref expr, ref blk, ref elseopt) => {
1725-
try!(self.print_if_let(&**pat, &**expr, &** blk, elseopt.as_ref().map(|e| &**e)));
1724+
ast::ExprIfLet(ref pats, ref expr, ref blk, ref elseopt) => {
1725+
try!(self.print_if_let(&**pats, &**expr, &** blk, elseopt.as_ref().map(|e| &**e)));
17261726
}
17271727
ast::ExprWhile(ref test, ref blk, opt_ident) => {
17281728
if let Some(ident) = opt_ident {
@@ -2253,6 +2253,19 @@ impl<'a> State<'a> {
22532253
self.ann.post(self, NodePat(pat))
22542254
}
22552255

2256+
pub fn print_pats(&mut self, pats: &[ast::Pat]) -> IoResult<()> {
2257+
let mut first = true;
2258+
for ref p in pats {
2259+
if first {
2260+
first = false;
2261+
} else {
2262+
try!(space(&mut self.s));
2263+
try!(self.word_space("|"));
2264+
}
2265+
try!(self.print_pat(&**p));
2266+
}
2267+
}
2268+
22562269
fn print_arm(&mut self, arm: &ast::Arm) -> IoResult<()> {
22572270
// I have no idea why this check is necessary, but here it
22582271
// is :(

src/libsyntax/visit.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,8 +805,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
805805
visitor.visit_expr(&**subexpression);
806806
visitor.visit_block(&**block)
807807
}
808-
ExprIfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
809-
visitor.visit_pat(&**pattern);
808+
ExprIfLet(ref patterns, ref subexpression, ref if_block, ref optional_else) => {
809+
for pattern in patterns {
810+
visitor.visit_pat(&**pattern)
811+
}
810812
visitor.visit_expr(&**subexpression);
811813
visitor.visit_block(&**if_block);
812814
walk_expr_opt(visitor, optional_else);

0 commit comments

Comments
 (0)