Make parse_seq_to_before_tokens take expected/nonexpected tokens, use in parse_precise_capturing_syntax

This commit is contained in:
Michael Goulet 2024-06-05 17:02:18 -04:00
parent 59e2c01c22
commit 68bd001c00
8 changed files with 38 additions and 51 deletions

View File

@ -1,7 +1,6 @@
use super::pat::Expected; use super::pat::Expected;
use super::{ use super::{
BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType,
TokenExpectType, TokenType,
}; };
use crate::errors::{ use crate::errors::{
AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, BadQPathStage2, BadTypePlus, AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, BadQPathStage2, BadTypePlus,
@ -1045,9 +1044,7 @@ pub(super) fn recover_closure_body(
/// passes through any errors encountered. Used for error recovery. /// passes through any errors encountered. Used for error recovery.
pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) {
if let Err(err) = if let Err(err) =
self.parse_seq_to_before_tokens(kets, SeqSep::none(), TokenExpectType::Expect, |p| { self.parse_seq_to_before_tokens(kets, &[], SeqSep::none(), |p| Ok(p.parse_token_tree()))
Ok(p.parse_token_tree())
})
{ {
err.cancel(); err.cancel();
} }

View File

@ -4,7 +4,7 @@
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{ use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, Trailing, TrailingToken, SemiColonMode, SeqSep, TokenType, Trailing, TrailingToken,
}; };
use crate::errors; use crate::errors;
@ -2456,9 +2456,9 @@ fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> {
self.expect(&token::BinOp(token::Or))?; self.expect(&token::BinOp(token::Or))?;
let args = self let args = self
.parse_seq_to_before_tokens( .parse_seq_to_before_tokens(
&[&token::BinOp(token::Or), &token::OrOr], &[&token::BinOp(token::Or)],
&[&token::OrOr],
SeqSep::trailing_allowed(token::Comma), SeqSep::trailing_allowed(token::Comma),
TokenExpectType::NoExpect,
|p| p.parse_fn_block_param(), |p| p.parse_fn_block_param(),
)? )?
.0; .0;

View File

@ -335,18 +335,6 @@ fn to_string(&self) -> String {
} }
} }
/// Used by [`Parser::expect_any_with_type`].
#[derive(Copy, Clone, Debug)]
enum TokenExpectType {
/// Unencountered tokens are inserted into [`Parser::expected_tokens`].
/// See [`Parser::check`].
Expect,
/// Unencountered tokens are not inserted into [`Parser::expected_tokens`].
/// See [`Parser::check_noexpect`].
NoExpect,
}
/// A sequence separator. /// A sequence separator.
#[derive(Debug)] #[derive(Debug)]
struct SeqSep { struct SeqSep {
@ -807,11 +795,13 @@ fn expect_gt(&mut self) -> PResult<'a, ()> {
} }
/// Checks if the next token is contained within `kets`, and returns `true` if so. /// Checks if the next token is contained within `kets`, and returns `true` if so.
fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool { fn expect_any_with_type(
kets.iter().any(|k| match expect { &mut self,
TokenExpectType::Expect => self.check(k), kets_expected: &[&TokenKind],
TokenExpectType::NoExpect => self.check_noexpect(k), kets_not_expected: &[&TokenKind],
}) ) -> bool {
kets_expected.iter().any(|k| self.check(k))
|| kets_not_expected.iter().any(|k| self.check_noexpect(k))
} }
/// Parses a sequence until the specified delimiters. The function /// Parses a sequence until the specified delimiters. The function
@ -819,9 +809,9 @@ fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType)
/// closing bracket. /// closing bracket.
fn parse_seq_to_before_tokens<T>( fn parse_seq_to_before_tokens<T>(
&mut self, &mut self,
kets: &[&TokenKind], kets_expected: &[&TokenKind],
kets_not_expected: &[&TokenKind],
sep: SeqSep, sep: SeqSep,
expect: TokenExpectType,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> { ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
let mut first = true; let mut first = true;
@ -829,7 +819,7 @@ fn parse_seq_to_before_tokens<T>(
let mut trailing = Trailing::No; let mut trailing = Trailing::No;
let mut v = ThinVec::new(); let mut v = ThinVec::new();
while !self.expect_any_with_type(kets, expect) { while !self.expect_any_with_type(kets_expected, kets_not_expected) {
if let token::CloseDelim(..) | token::Eof = self.token.kind { if let token::CloseDelim(..) | token::Eof = self.token.kind {
break; break;
} }
@ -927,7 +917,8 @@ fn parse_seq_to_before_tokens<T>(
if self.token == token::Colon { if self.token == token::Colon {
// we will try to recover in `maybe_recover_struct_lit_bad_delims` // we will try to recover in `maybe_recover_struct_lit_bad_delims`
return Err(expect_err); return Err(expect_err);
} else if let [token::CloseDelim(Delimiter::Parenthesis)] = kets } else if let [token::CloseDelim(Delimiter::Parenthesis)] =
kets_expected
{ {
return Err(expect_err); return Err(expect_err);
} else { } else {
@ -940,7 +931,9 @@ fn parse_seq_to_before_tokens<T>(
} }
} }
} }
if sep.trailing_sep_allowed && self.expect_any_with_type(kets, expect) { if sep.trailing_sep_allowed
&& self.expect_any_with_type(kets_expected, kets_not_expected)
{
trailing = Trailing::Yes; trailing = Trailing::Yes;
break; break;
} }
@ -1020,7 +1013,7 @@ fn parse_seq_to_before_end<T>(
sep: SeqSep, sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> { ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f) self.parse_seq_to_before_tokens(&[ket], &[], sep, f)
} }
/// Parses a sequence, including only the closing delimiter. The function /// Parses a sequence, including only the closing delimiter. The function

View File

@ -9,7 +9,7 @@
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::token::{self, BinOpToken, Delimiter, Token, TokenKind};
use rustc_ast::util::case::Case; use rustc_ast::util::case::Case;
use rustc_ast::{ use rustc_ast::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
@ -694,9 +694,14 @@ fn parse_precise_capturing_args(
&mut self, &mut self,
) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> { ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
let lo = self.token.span; let lo = self.token.span;
let (args, _) = self.parse_unspanned_seq( self.expect_lt()?;
&TokenKind::Lt, let (args, _, _) = self.parse_seq_to_before_tokens(
&TokenKind::Gt, &[&TokenKind::Gt],
&[
&TokenKind::Ge,
&TokenKind::BinOp(BinOpToken::Shr),
&TokenKind::BinOpEq(BinOpToken::Shr),
],
SeqSep::trailing_allowed(token::Comma), SeqSep::trailing_allowed(token::Comma),
|self_| { |self_| {
if self_.check_keyword(kw::SelfUpper) { if self_.check_keyword(kw::SelfUpper) {
@ -717,6 +722,7 @@ fn parse_precise_capturing_args(
} }
}, },
)?; )?;
self.expect_gt()?;
Ok((args, lo.to(self.prev_token.span))) Ok((args, lo.to(self.prev_token.span)))
} }

View File

@ -4,6 +4,5 @@
fn hello() -> impl use<'a {}> Sized {} fn hello() -> impl use<'a {}> Sized {}
//~^ ERROR expected one of `,` or `>`, found `{` //~^ ERROR expected one of `,` or `>`, found `{`
//~| ERROR expected item, found `>`
fn main() {} fn main() {}

View File

@ -4,13 +4,5 @@ error: expected one of `,` or `>`, found `{`
LL | fn hello() -> impl use<'a {}> Sized {} LL | fn hello() -> impl use<'a {}> Sized {}
| ^ expected one of `,` or `>` | ^ expected one of `,` or `>`
error: expected item, found `>` error: aborting due to 1 previous error
--> $DIR/unexpected-token.rs:5:29
|
LL | fn hello() -> impl use<'a {}> Sized {}
| ^ expected item
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
error: aborting due to 2 previous errors

View File

@ -1,6 +1,6 @@
fn a() { fn a() {
[0; [|_: _ &_| ()].len()] [0; [|_: _ &_| ()].len()]
//~^ ERROR expected `,`, found `&` //~^ ERROR expected one of `,` or `|`, found `&`
//~| ERROR type annotations needed //~| ERROR type annotations needed
} }
@ -11,7 +11,7 @@ fn b() {
fn c() { fn c() {
[0; [|&_: _ &_| {}; 0 ].len()] [0; [|&_: _ &_| {}; 0 ].len()]
//~^ ERROR expected `,`, found `&` //~^ ERROR expected one of `,` or `|`, found `&`
//~| ERROR type annotations needed //~| ERROR type annotations needed
} }

View File

@ -1,8 +1,8 @@
error: expected `,`, found `&` error: expected one of `,` or `|`, found `&`
--> $DIR/issue-66706.rs:2:16 --> $DIR/issue-66706.rs:2:16
| |
LL | [0; [|_: _ &_| ()].len()] LL | [0; [|_: _ &_| ()].len()]
| -^ expected `,` | -^ expected one of `,` or `|`
| | | |
| help: missing `,` | help: missing `,`
@ -12,11 +12,11 @@ error: expected identifier, found reserved identifier `_`
LL | [0; [|f @ &ref _| {} ; 0 ].len() ]; LL | [0; [|f @ &ref _| {} ; 0 ].len() ];
| ^ expected identifier, found reserved identifier | ^ expected identifier, found reserved identifier
error: expected `,`, found `&` error: expected one of `,` or `|`, found `&`
--> $DIR/issue-66706.rs:13:17 --> $DIR/issue-66706.rs:13:17
| |
LL | [0; [|&_: _ &_| {}; 0 ].len()] LL | [0; [|&_: _ &_| {}; 0 ].len()]
| -^ expected `,` | -^ expected one of `,` or `|`
| | | |
| help: missing `,` | help: missing `,`