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

View File

@ -4,7 +4,7 @@
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, Trailing, TrailingToken,
SemiColonMode, SeqSep, TokenType, Trailing, TrailingToken,
};
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))?;
let args = self
.parse_seq_to_before_tokens(
&[&token::BinOp(token::Or), &token::OrOr],
&[&token::BinOp(token::Or)],
&[&token::OrOr],
SeqSep::trailing_allowed(token::Comma),
TokenExpectType::NoExpect,
|p| p.parse_fn_block_param(),
)?
.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.
#[derive(Debug)]
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.
fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool {
kets.iter().any(|k| match expect {
TokenExpectType::Expect => self.check(k),
TokenExpectType::NoExpect => self.check_noexpect(k),
})
fn expect_any_with_type(
&mut self,
kets_expected: &[&TokenKind],
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
@ -819,9 +809,9 @@ fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType)
/// closing bracket.
fn parse_seq_to_before_tokens<T>(
&mut self,
kets: &[&TokenKind],
kets_expected: &[&TokenKind],
kets_not_expected: &[&TokenKind],
sep: SeqSep,
expect: TokenExpectType,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
let mut first = true;
@ -829,7 +819,7 @@ fn parse_seq_to_before_tokens<T>(
let mut trailing = Trailing::No;
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 {
break;
}
@ -927,7 +917,8 @@ fn parse_seq_to_before_tokens<T>(
if self.token == token::Colon {
// we will try to recover in `maybe_recover_struct_lit_bad_delims`
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);
} 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;
break;
}
@ -1020,7 +1013,7 @@ fn parse_seq_to_before_end<T>(
sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> 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

View File

@ -9,7 +9,7 @@
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
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::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
@ -694,9 +694,14 @@ fn parse_precise_capturing_args(
&mut self,
) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
let lo = self.token.span;
let (args, _) = self.parse_unspanned_seq(
&TokenKind::Lt,
&TokenKind::Gt,
self.expect_lt()?;
let (args, _, _) = self.parse_seq_to_before_tokens(
&[&TokenKind::Gt],
&[
&TokenKind::Ge,
&TokenKind::BinOp(BinOpToken::Shr),
&TokenKind::BinOpEq(BinOpToken::Shr),
],
SeqSep::trailing_allowed(token::Comma),
|self_| {
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)))
}

View File

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

View File

@ -4,13 +4,5 @@ error: expected one of `,` or `>`, found `{`
LL | fn hello() -> impl use<'a {}> Sized {}
| ^ expected one of `,` or `>`
error: expected item, found `>`
--> $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
error: aborting due to 1 previous error

View File

@ -1,6 +1,6 @@
fn a() {
[0; [|_: _ &_| ()].len()]
//~^ ERROR expected `,`, found `&`
//~^ ERROR expected one of `,` or `|`, found `&`
//~| ERROR type annotations needed
}
@ -11,7 +11,7 @@ fn b() {
fn c() {
[0; [|&_: _ &_| {}; 0 ].len()]
//~^ ERROR expected `,`, found `&`
//~^ ERROR expected one of `,` or `|`, found `&`
//~| 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
|
LL | [0; [|_: _ &_| ()].len()]
| -^ expected `,`
| -^ expected one of `,` or `|`
| |
| help: missing `,`
@ -12,11 +12,11 @@ error: expected identifier, found reserved identifier `_`
LL | [0; [|f @ &ref _| {} ; 0 ].len() ];
| ^ expected identifier, found reserved identifier
error: expected `,`, found `&`
error: expected one of `,` or `|`, found `&`
--> $DIR/issue-66706.rs:13:17
|
LL | [0; [|&_: _ &_| {}; 0 ].len()]
| -^ expected `,`
| -^ expected one of `,` or `|`
| |
| help: missing `,`