diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 83 |
2 files changed, 72 insertions, 27 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 96c89d3176a..dcb55fb572f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -906,7 +906,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu not currently handle destructors.", cfg_fn!(thread_local))), - ("rustc_on_unimplemented", Normal, template!(List: + ("rustc_on_unimplemented", Whitelisted, template!(List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message"), Gated(Stability::Unstable, @@ -962,6 +962,20 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_layout_scalar_valid_range_start", Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_layout_scalar_valid_range_start]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), + ("rustc_layout_scalar_valid_range_end", Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_layout_scalar_valid_range_end]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), ("rustc_regions", Normal, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_regions]` attribute \ diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 79c1f0cb4cc..ae8e57d54de 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2626,7 +2626,13 @@ impl<'a> Parser<'a> { let mut trailing_comma = false; let mut recovered = false; while self.token != token::CloseDelim(token::Paren) { - es.push(self.parse_expr()?); + es.push(match self.parse_expr() { + Ok(es) => es, + Err(err) => { + // recover from parse error in tuple list + return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))); + } + }); recovered = self.expect_one_of( &[], &[token::Comma, token::CloseDelim(token::Paren)], @@ -3237,36 +3243,54 @@ impl<'a> Parser<'a> { } if self.expr_is_complete(&e) { break; } match self.token { - // expr(...) - token::OpenDelim(token::Paren) => { - let es = self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| Ok(p.parse_expr()?) - )?; - hi = self.prev_span; - - let nd = self.mk_call(e, es); - e = self.mk_expr(lo.to(hi), nd, ThinVec::new()); - } + // expr(...) + token::OpenDelim(token::Paren) => { + let seq = self.parse_unspanned_seq( + &token::OpenDelim(token::Paren), + &token::CloseDelim(token::Paren), + SeqSep::trailing_allowed(token::Comma), + |p| Ok(p.parse_expr()?) + ).map(|es| { + let nd = self.mk_call(e, es); + let hi = self.prev_span; + self.mk_expr(lo.to(hi), nd, ThinVec::new()) + }); + e = self.recover_seq_parse_error(token::Paren, lo, seq); + } - // expr[...] - // Could be either an index expression or a slicing expression. - token::OpenDelim(token::Bracket) => { - self.bump(); - let ix = self.parse_expr()?; - hi = self.span; - self.expect(&token::CloseDelim(token::Bracket))?; - let index = self.mk_index(e, ix); - e = self.mk_expr(lo.to(hi), index, ThinVec::new()) - } - _ => return Ok(e) + // expr[...] + // Could be either an index expression or a slicing expression. + token::OpenDelim(token::Bracket) => { + self.bump(); + let ix = self.parse_expr()?; + hi = self.span; + self.expect(&token::CloseDelim(token::Bracket))?; + let index = self.mk_index(e, ix); + e = self.mk_expr(lo.to(hi), index, ThinVec::new()) + } + _ => return Ok(e) } } return Ok(e); } + fn recover_seq_parse_error( + &mut self, + delim: token::DelimToken, + lo: Span, + result: PResult<'a, P<Expr>>, + ) -> P<Expr> { + match result { + Ok(x) => x, + Err(mut err) => { + err.emit(); + // recover from parse error + self.consume_block(delim); + self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) + } + } + } + crate fn process_potential_macro_variable(&mut self) { let (token, span) = match self.token { token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() && @@ -4253,7 +4277,14 @@ impl<'a> Parser<'a> { // Trailing commas are significant because (p) and (p,) are different patterns. fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> { self.expect(&token::OpenDelim(token::Paren))?; - let result = self.parse_pat_list()?; + let result = match self.parse_pat_list() { + Ok(result) => result, + Err(mut err) => { // recover from parse error in tuple pattern list + err.emit(); + self.consume_block(token::Paren); + return Ok((vec![], Some(0), false)); + } + }; self.expect(&token::CloseDelim(token::Paren))?; Ok(result) } |
