diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2018-02-24 15:52:17 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-24 15:52:17 -0800 |
| commit | 9523c82543a8955393e76004bccfb1b26e4e06c1 (patch) | |
| tree | fbafef4b45e775d59c62defed0d5261a956be219 /src | |
| parent | 7e6829938c198afe033119f1927459c64d2ea4d7 (diff) | |
| parent | 8640a51ff8d580bbb87aa3dc0ff8bacbad111010 (diff) | |
| download | rust-9523c82543a8955393e76004bccfb1b26e4e06c1.tar.gz rust-9523c82543a8955393e76004bccfb1b26e4e06c1.zip | |
Rollup merge of #48490 - petrochenkov:orpat, r=eddyb
Implement multiple patterns with `|` in `if let` and `while let` (RFC 2175) cc https://github.com/rust-lang/rust/issues/48215
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/hir/lowering.rs | 12 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 36 | ||||
| -rw-r--r-- | src/librustc_save_analysis/dump_visitor.rs | 163 | ||||
| -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 | 8 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 41 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 8 | ||||
| -rw-r--r-- | src/test/run-pass/rfc-2175-or-if-while-let/basic.rs | 30 | ||||
| -rw-r--r-- | src/test/ui/feature-gate-if_while_or_patterns.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/feature-gate-if_while_or_patterns.stderr | 22 |
12 files changed, 231 insertions, 128 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e3af2850538..89ed47ea194 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2956,7 +2956,7 @@ impl<'a> LoweringContext<'a> { // Desugar ExprIfLet // From: `if let <pat> = <sub_expr> <body> [<else_opt>]` - ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => { + ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => { // to: // // match <sub_expr> { @@ -2970,8 +2970,8 @@ impl<'a> LoweringContext<'a> { { let body = self.lower_block(body, false); let body_expr = P(self.expr_block(body, ThinVec::new())); - let pat = self.lower_pat(pat); - arms.push(self.arm(hir_vec![pat], body_expr)); + let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect(); + arms.push(self.arm(pats, body_expr)); } // _ => [<else_opt>|()] @@ -3000,7 +3000,7 @@ impl<'a> LoweringContext<'a> { // Desugar ExprWhileLet // From: `[opt_ident]: while let <pat> = <sub_expr> <body>` - ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_label) => { + ExprKind::WhileLet(ref pats, ref sub_expr, ref body, opt_label) => { // to: // // [opt_ident]: loop { @@ -3021,8 +3021,8 @@ impl<'a> LoweringContext<'a> { // `<pat> => <body>` let pat_arm = { let body_expr = P(self.expr_block(body, ThinVec::new())); - let pat = self.lower_pat(pat); - self.arm(hir_vec![pat], body_expr) + let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect(); + self.arm(pats, body_expr) }; // `_ => break` diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e6b9150fa3a..e4e9ee58330 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -59,6 +59,7 @@ use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue}; use syntax::parse::token; +use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use errors::{DiagnosticBuilder, DiagnosticId}; @@ -2329,17 +2330,17 @@ impl<'a> Resolver<'a> { // check that all of the arms in an or-pattern have exactly the // same set of bindings, with the same binding modes for each. - fn check_consistent_bindings(&mut self, arm: &Arm) { - if arm.pats.is_empty() { + fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) { + if pats.is_empty() { return; } let mut missing_vars = FxHashMap(); let mut inconsistent_vars = FxHashMap(); - for (i, p) in arm.pats.iter().enumerate() { + for (i, p) in pats.iter().enumerate() { let map_i = self.binding_mode_map(&p); - for (j, q) in arm.pats.iter().enumerate() { + for (j, q) in pats.iter().enumerate() { if i == j { continue; } @@ -2404,9 +2405,8 @@ impl<'a> Resolver<'a> { self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); } - // This has to happen *after* we determine which - // pat_idents are variants - self.check_consistent_bindings(arm); + // This has to happen *after* we determine which pat_idents are variants + self.check_consistent_bindings(&arm.pats); walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); @@ -2490,7 +2490,9 @@ impl<'a> Resolver<'a> { &ident.node.name.as_str()) ); } - Some(..) if pat_src == PatternSource::Match => { + Some(..) if pat_src == PatternSource::Match || + pat_src == PatternSource::IfLet || + pat_src == PatternSource::WhileLet => { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node]; @@ -3480,11 +3482,16 @@ impl<'a> Resolver<'a> { visit::walk_expr(self, expr); } - ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { + ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => { self.visit_expr(subexpression); self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap()); + let mut bindings_list = FxHashMap(); + for pat in pats { + self.resolve_pattern(pat, PatternSource::IfLet, &mut bindings_list); + } + // This has to happen *after* we determine which pat_idents are variants + self.check_consistent_bindings(pats); self.visit_block(if_block); self.ribs[ValueNS].pop(); @@ -3500,11 +3507,16 @@ impl<'a> Resolver<'a> { }); } - ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { + ExprKind::WhileLet(ref pats, ref subexpression, ref block, label) => { self.with_resolved_label(label, expr.id, |this| { this.visit_expr(subexpression); this.ribs[ValueNS].push(Rib::new(NormalRibKind)); - this.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap()); + let mut bindings_list = FxHashMap(); + for pat in pats { + this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list); + } + // This has to happen *after* we determine which pat_idents are variants + this.check_consistent_bindings(pats); this.visit_block(block); this.ribs[ValueNS].pop(); }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index bf82b077423..6e986041013 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1031,6 +1031,81 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } + fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) { + let mut collector = PathCollector::new(); + for pattern in pats { + // collect paths from the arm's patterns + collector.visit_pat(&pattern); + self.visit_pat(&pattern); + } + + // process collected paths + for (id, i, sp, immut) in collector.collected_idents { + match self.save_ctxt.get_path_def(id) { + HirDef::Local(id) => { + let mut value = if immut == ast::Mutability::Immutable { + self.span.snippet(sp).to_string() + } else { + "<mutable>".to_string() + }; + let hir_id = self.tcx.hir.node_to_hir_id(id); + let typ = self.save_ctxt + .tables + .node_id_to_type_opt(hir_id) + .map(|t| t.to_string()) + .unwrap_or(String::new()); + value.push_str(": "); + value.push_str(&typ); + + if !self.span.filter_generated(Some(sp), sp) { + let qualname = format!("{}${}", i.to_string(), id); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sp); + + self.dumper.dump_def( + &Access { + public: false, + reachable: false, + }, + Def { + kind: DefKind::Local, + id, + span, + name: i.to_string(), + qualname, + value: typ, + parent: None, + children: vec![], + decl_id: None, + docs: String::new(), + sig: None, + attributes: vec![], + }, + ); + } + } + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) | + HirDef::Const(..) | + HirDef::AssociatedConst(..) | + HirDef::Struct(..) | + HirDef::Variant(..) | + HirDef::TyAlias(..) | + HirDef::AssociatedTy(..) | + HirDef::SelfTy(..) => { + self.dump_path_ref(id, &ast::Path::from_ident(sp, i)); + } + def => error!( + "unexpected definition kind when processing collected idents: {:?}", + def + ), + } + } + + for (id, ref path) in collector.collected_paths { + self.process_path(id, path); + } + } fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) { // The local could declare multiple new vars, we must walk the @@ -1622,17 +1697,21 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc v.nest_scope(ex.id, |v| v.visit_expr(body)) }); } - ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) | - ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => { + ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => { let value = self.span.snippet(subexpression.span); self.process_var_decl(pattern, value); debug!("for loop, walk sub-expr: {:?}", subexpression.node); self.visit_expr(subexpression); visit::walk_block(self, block); } - ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => { - let value = self.span.snippet(subexpression.span); - self.process_var_decl(pattern, value); + ast::ExprKind::WhileLet(ref pats, ref subexpression, ref block, _) => { + self.process_var_decl_multi(pats); + debug!("for loop, walk sub-expr: {:?}", subexpression.node); + self.visit_expr(subexpression); + visit::walk_block(self, block); + } + ast::ExprKind::IfLet(ref pats, ref subexpression, ref block, ref opt_else) => { + self.process_var_decl_multi(pats); self.visit_expr(subexpression); visit::walk_block(self, block); opt_else.as_ref().map(|el| self.visit_expr(el)); @@ -1661,79 +1740,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } fn visit_arm(&mut self, arm: &'l ast::Arm) { - let mut collector = PathCollector::new(); - for pattern in &arm.pats { - // collect paths from the arm's patterns - collector.visit_pat(&pattern); - self.visit_pat(&pattern); - } - - // process collected paths - for (id, i, sp, immut) in collector.collected_idents { - match self.save_ctxt.get_path_def(id) { - HirDef::Local(id) => { - let mut value = if immut == ast::Mutability::Immutable { - self.span.snippet(sp).to_string() - } else { - "<mutable>".to_string() - }; - let hir_id = self.tcx.hir.node_to_hir_id(id); - let typ = self.save_ctxt - .tables - .node_id_to_type_opt(hir_id) - .map(|t| t.to_string()) - .unwrap_or(String::new()); - value.push_str(": "); - value.push_str(&typ); - - if !self.span.filter_generated(Some(sp), sp) { - let qualname = format!("{}${}", i.to_string(), id); - let id = ::id_from_node_id(id, &self.save_ctxt); - let span = self.span_from_span(sp); - - self.dumper.dump_def( - &Access { - public: false, - reachable: false, - }, - Def { - kind: DefKind::Local, - id, - span, - name: i.to_string(), - qualname, - value: typ, - parent: None, - children: vec![], - decl_id: None, - docs: String::new(), - sig: None, - attributes: vec![], - }, - ); - } - } - HirDef::StructCtor(..) | - HirDef::VariantCtor(..) | - HirDef::Const(..) | - HirDef::AssociatedConst(..) | - HirDef::Struct(..) | - HirDef::Variant(..) | - HirDef::TyAlias(..) | - HirDef::AssociatedTy(..) | - HirDef::SelfTy(..) => { - self.dump_path_ref(id, &ast::Path::from_ident(sp, i)); - } - def => error!( - "unexpected definition kind when processing collected idents: {:?}", - def - ), - } - } - - for (id, ref path) in collector.collected_paths { - self.process_path(id, path); - } + self.process_var_decl_multi(&arm.pats); walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); } 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 62233f97e75..4d457f4864a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3228,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()?; @@ -3238,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` @@ -3329,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); } diff --git a/src/test/run-pass/rfc-2175-or-if-while-let/basic.rs b/src/test/run-pass/rfc-2175-or-if-while-let/basic.rs new file mode 100644 index 00000000000..a516a3e5dcd --- /dev/null +++ b/src/test/run-pass/rfc-2175-or-if-while-let/basic.rs @@ -0,0 +1,30 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(if_while_or_patterns)] + +enum E { + V(u8), + U(u8), + W, +} +use E::*; + +fn main() { + let mut e = V(10); + + if let V(x) | U(x) = e { + assert_eq!(x, 10); + } + while let V(x) | U(x) = e { + assert_eq!(x, 10); + e = W; + } +} diff --git a/src/test/ui/feature-gate-if_while_or_patterns.rs b/src/test/ui/feature-gate-if_while_or_patterns.rs new file mode 100644 index 00000000000..3df140c77fc --- /dev/null +++ b/src/test/ui/feature-gate-if_while_or_patterns.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable + ; + } + while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable + break; + } +} diff --git a/src/test/ui/feature-gate-if_while_or_patterns.stderr b/src/test/ui/feature-gate-if_while_or_patterns.stderr new file mode 100644 index 00000000000..c906fa5a2f4 --- /dev/null +++ b/src/test/ui/feature-gate-if_while_or_patterns.stderr @@ -0,0 +1,22 @@ +error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215) + --> $DIR/feature-gate-if_while_or_patterns.rs:12:5 + | +12 | / if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable +13 | | ; +14 | | } + | |_____^ + | + = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable + +error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215) + --> $DIR/feature-gate-if_while_or_patterns.rs:15:5 + | +15 | / while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable +16 | | break; +17 | | } + | |_____^ + | + = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable + +error: aborting due to 2 previous errors + |
