diff options
| author | bors <bors@rust-lang.org> | 2018-02-25 02:07:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-02-25 02:07:14 +0000 |
| commit | 026339e42ba11a559767029d933d1197aefb877a (patch) | |
| tree | 884a690f24c660b4ece0ea6818846920f82631f4 /src/libsyntax | |
| parent | 28a1e4ffefa2620ad9f4179ea339833448874fd3 (diff) | |
| parent | 52047f0ba0d1b1144073963b9b009399d32fb984 (diff) | |
| download | rust-026339e42ba11a559767029d933d1197aefb877a.tar.gz rust-026339e42ba11a559767029d933d1197aefb877a.zip | |
Auto merge of #48520 - Manishearth:rollup, r=Manishearth
Rollup of 15 pull requests - Successful merges: #47689, #48110, #48197, #48296, #48386, #48392, #48404, #48415, #48441, #48448, #48452, #48481, #48490, #48499, #48503 - Failed merges:
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 41 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 8 |
6 files changed, 56 insertions, 38 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c7ce7fffaa2..6609b77b132 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1085,7 +1085,7 @@ pub enum ExprKind { /// `if let pat = expr { block } else { expr }` /// /// This is desugared to a `match` expression. - IfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>), + IfLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<P<Expr>>), /// A while loop, with an optional label /// /// `'label: while expr { block }` @@ -1095,7 +1095,7 @@ pub enum ExprKind { /// `'label: while let pat = expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Label>), + WhileLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<Label>), /// A for loop, with an optional label /// /// `'label: for pat in expr { block }` diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ba24d7f914b..1ebf52e9fe8 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -446,6 +446,9 @@ declare_features! ( // Use `?` as the Kleene "at most one" operator (active, macro_at_most_once_rep, "1.25.0", Some(48075)), + + // Multiple patterns with `|` in `if let` and `while let` + (active, if_while_or_patterns, "1.26.0", Some(48215)), ); declare_features! ( @@ -1618,6 +1621,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::Catch(_) => { gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental"); } + ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => { + if pats.len() > 1 { + gate_feature_post!(&self, if_while_or_patterns, e.span, + "multiple patterns in `if let` and `while let` are unstable"); + } + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1a2025b073b..e8eb75f5e60 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1210,8 +1210,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_block(tr), fl.map(|x| folder.fold_expr(x))) } - ExprKind::IfLet(pat, expr, tr, fl) => { - ExprKind::IfLet(folder.fold_pat(pat), + ExprKind::IfLet(pats, expr, tr, fl) => { + ExprKind::IfLet(pats.move_map(|pat| folder.fold_pat(pat)), folder.fold_expr(expr), folder.fold_block(tr), fl.map(|x| folder.fold_expr(x))) @@ -1221,8 +1221,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_block(body), opt_label.map(|label| folder.fold_label(label))) } - ExprKind::WhileLet(pat, expr, body, opt_label) => { - ExprKind::WhileLet(folder.fold_pat(pat), + ExprKind::WhileLet(pats, expr, body, opt_label) => { + ExprKind::WhileLet(pats.move_map(|pat| folder.fold_pat(pat)), folder.fold_expr(expr), folder.fold_block(body), opt_label.map(|label| folder.fold_label(label))) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index efc191f24ac..4d457f4864a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -405,11 +405,14 @@ impl TokenType { } } -// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`, -// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`. -fn can_continue_type_after_ident(t: &token::Token) -> bool { +/// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`, +/// `IDENT<<u8 as Trait>::AssocTy>`. +/// +/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes +/// that IDENT is not the ident of a fn trait +fn can_continue_type_after_non_fn_ident(t: &token::Token) -> bool { t == &token::ModSep || t == &token::Lt || - t == &token::BinOp(token::Shl) || t == &token::OpenDelim(token::Paren) + t == &token::BinOp(token::Shl) } /// Information about the path to a module. @@ -1321,7 +1324,7 @@ impl<'a> Parser<'a> { pub fn token_is_bare_fn_keyword(&mut self) -> bool { self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) || - self.check_keyword(keywords::Extern) + self.check_keyword(keywords::Extern) && self.is_extern_non_path() } fn eat_label(&mut self) -> Option<Label> { @@ -1619,7 +1622,8 @@ impl<'a> Parser<'a> { impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(bounds) } else if self.check_keyword(keywords::Dyn) && - self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) { + self.look_ahead(1, |t| t.can_begin_bound() && + !can_continue_type_after_non_fn_ident(t)) { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. let bounds = self.parse_ty_param_bounds()?; @@ -3224,7 +3228,7 @@ impl<'a> Parser<'a> { -> PResult<'a, P<Expr>> { let lo = self.prev_span; self.expect_keyword(keywords::Let)?; - let pat = self.parse_pat()?; + let pats = self.parse_pats()?; self.expect(&token::Eq)?; let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; @@ -3234,7 +3238,7 @@ impl<'a> Parser<'a> { } else { (thn.span, None) }; - Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pat, expr, thn, els), attrs)) + Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs)) } // `move |args| expr` @@ -3325,13 +3329,13 @@ impl<'a> Parser<'a> { span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { self.expect_keyword(keywords::Let)?; - let pat = self.parse_pat()?; + let pats = self.parse_pats()?; self.expect(&token::Eq)?; let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); - return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_label), attrs)); + return Ok(self.mk_expr(span, ExprKind::WhileLet(pats, expr, body, opt_label), attrs)); } // parse `loop {...}`, `loop` token already eaten diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3dfe3c9e5b9..9cad9f46e98 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1767,11 +1767,11 @@ impl<'a> State<'a> { self.print_else(e.as_ref().map(|e| &**e)) } // "another else-if-let" - ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => { + ast::ExprKind::IfLet(ref pats, ref expr, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; self.s.word(" else if let ")?; - self.print_pat(pat)?; + self.print_pats(pats)?; self.s.space()?; self.word_space("=")?; self.print_expr_as_cond(expr)?; @@ -1805,10 +1805,10 @@ impl<'a> State<'a> { self.print_else(elseopt) } - pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block, + pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) -> io::Result<()> { self.head("if let")?; - self.print_pat(pat)?; + self.print_pats(pats)?; self.s.space()?; self.word_space("=")?; self.print_expr_as_cond(expr)?; @@ -2109,8 +2109,8 @@ impl<'a> State<'a> { ast::ExprKind::If(ref test, ref blk, ref elseopt) => { self.print_if(test, blk, elseopt.as_ref().map(|e| &**e))?; } - ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => { - self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?; + ast::ExprKind::IfLet(ref pats, ref expr, ref blk, ref elseopt) => { + self.print_if_let(pats, expr, blk, elseopt.as_ref().map(|e| &**e))?; } ast::ExprKind::While(ref test, ref blk, opt_label) => { if let Some(label) = opt_label { @@ -2122,13 +2122,13 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } - ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_label) => { + ast::ExprKind::WhileLet(ref pats, ref expr, ref blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident)?; self.word_space(":")?; } self.head("while let")?; - self.print_pat(pat)?; + self.print_pats(pats)?; self.s.space()?; self.word_space("=")?; self.print_expr_as_cond(expr)?; @@ -2664,6 +2664,20 @@ impl<'a> State<'a> { self.ann.post(self, NodePat(pat)) } + fn print_pats(&mut self, pats: &[P<ast::Pat>]) -> io::Result<()> { + let mut first = true; + for p in pats { + if first { + first = false; + } else { + self.s.space()?; + self.word_space("|")?; + } + self.print_pat(p)?; + } + Ok(()) + } + fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> { // I have no idea why this check is necessary, but here it // is :( @@ -2674,16 +2688,7 @@ impl<'a> State<'a> { self.ibox(0)?; self.maybe_print_comment(arm.pats[0].span.lo())?; self.print_outer_attributes(&arm.attrs)?; - let mut first = true; - for p in &arm.pats { - if first { - first = false; - } else { - self.s.space()?; - self.word_space("|")?; - } - self.print_pat(p)?; - } + self.print_pats(&arm.pats)?; self.s.space()?; if let Some(ref e) = arm.guard { self.word_space("if")?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4691ddafa36..640f90ecb4a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -705,15 +705,15 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(subexpression); visitor.visit_block(block); } - ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { - visitor.visit_pat(pattern); + ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => { + walk_list!(visitor, visit_pat, pats); visitor.visit_expr(subexpression); visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_label) => { + ExprKind::WhileLet(ref pats, ref subexpression, ref block, ref opt_label) => { walk_list!(visitor, visit_label, opt_label); - visitor.visit_pat(pattern); + walk_list!(visitor, visit_pat, pats); visitor.visit_expr(subexpression); visitor.visit_block(block); } |
