Add newtype for raw idents

This commit is contained in:
clubby789 2024-02-13 23:28:27 +00:00
parent cce6a6e22e
commit 06d6c62f80
24 changed files with 148 additions and 87 deletions

View file

@ -21,6 +21,7 @@ use crate::errors::{
use crate::fluent_generated as fluent;
use crate::parser;
use crate::parser::attr::InnerAttrPolicy;
use ast::token::IdentIsRaw;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
@ -264,7 +265,7 @@ impl<'a> Parser<'a> {
pub(super) fn expected_ident_found(
&mut self,
recover: bool,
) -> PResult<'a, (Ident, /* is_raw */ bool)> {
) -> PResult<'a, (Ident, IdentIsRaw)> {
if let TokenKind::DocComment(..) = self.prev_token.kind {
return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything {
span: self.prev_token.span,
@ -290,11 +291,11 @@ impl<'a> Parser<'a> {
let bad_token = self.token.clone();
// suggest prepending a keyword in identifier position with `r#`
let suggest_raw = if let Some((ident, false)) = self.token.ident()
let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident()
&& ident.is_raw_guess()
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind))
{
recovered_ident = Some((ident, true));
recovered_ident = Some((ident, IdentIsRaw::Yes));
// `Symbol::to_string()` is different from `Symbol::into_diagnostic_arg()`,
// which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#`
@ -320,7 +321,7 @@ impl<'a> Parser<'a> {
let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, valid_portion)| {
let (invalid, valid) = self.token.span.split_at(len as u32);
recovered_ident = Some((Ident::new(valid_portion, valid), false));
recovered_ident = Some((Ident::new(valid_portion, valid), IdentIsRaw::No));
HelpIdentifierStartsWithNumber { num_span: invalid }
});
@ -653,9 +654,9 @@ impl<'a> Parser<'a> {
// positive for a `cr#` that wasn't intended to start a c-string literal, but identifying
// that in the parser requires unbounded lookahead, so we only add a hint to the existing
// error rather than replacing it entirely.
if ((self.prev_token.kind == TokenKind::Ident(sym::c, false)
if ((self.prev_token.kind == TokenKind::Ident(sym::c, IdentIsRaw::No)
&& matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. })))
|| (self.prev_token.kind == TokenKind::Ident(sym::cr, false)
|| (self.prev_token.kind == TokenKind::Ident(sym::cr, IdentIsRaw::No)
&& matches!(
&self.token.kind,
TokenKind::Literal(token::Lit { kind: token::Str, .. }) | token::Pound

View file

@ -10,6 +10,7 @@ use super::{
use crate::errors;
use crate::maybe_recover_from_interpolated_ty_qpath;
use ast::mut_visit::{noop_visit_expr, MutVisitor};
use ast::token::IdentIsRaw;
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment};
use core::mem;
use rustc_ast::ptr::P;
@ -128,7 +129,7 @@ impl<'a> Parser<'a> {
match self.parse_expr_res(restrictions, None) {
Ok(expr) => Ok(expr),
Err(err) => match self.token.ident() {
Some((Ident { name: kw::Underscore, .. }, false))
Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No))
if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
{
// Special-case handling of `foo(_, _, _)`
@ -459,7 +460,9 @@ impl<'a> Parser<'a> {
return None;
}
(Some(op), _) => (op, self.token.span),
(None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
(None, Some((Ident { name: sym::and, span }, IdentIsRaw::No)))
if self.may_recover() =>
{
self.dcx().emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "and".into(),
@ -467,7 +470,7 @@ impl<'a> Parser<'a> {
});
(AssocOp::LAnd, span)
}
(None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => {
(None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
self.dcx().emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "or".into(),
@ -744,7 +747,7 @@ impl<'a> Parser<'a> {
(
// `foo: `
ExprKind::Path(None, ast::Path { segments, .. }),
token::Ident(kw::For | kw::Loop | kw::While, false),
token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
) if segments.len() == 1 => {
let snapshot = self.create_snapshot_for_diagnostic();
let label = Label {
@ -957,19 +960,20 @@ impl<'a> Parser<'a> {
fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
loop {
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
// we are using noexpect here because we don't expect a `?` directly after a `return`
// which could be suggested otherwise
self.eat_noexpect(&token::Question)
} else {
self.eat(&token::Question)
};
let has_question =
if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
// we are using noexpect here because we don't expect a `?` directly after a `return`
// which could be suggested otherwise
self.eat_noexpect(&token::Question)
} else {
self.eat(&token::Question)
};
if has_question {
// `expr?`
e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
continue;
}
let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
// we are using noexpect here because we don't expect a `.` directly after a `return`
// which could be suggested otherwise
self.eat_noexpect(&token::Dot)
@ -1128,19 +1132,19 @@ impl<'a> Parser<'a> {
// 1.
DestructuredFloat::TrailingDot(sym, ident_span, dot_span) => {
assert!(suffix.is_none());
self.token = Token::new(token::Ident(sym, false), ident_span);
self.token = Token::new(token::Ident(sym, IdentIsRaw::No), ident_span);
let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
self.parse_expr_tuple_field_access(lo, base, sym, None, Some(next_token))
}
// 1.2 | 1.2e3
DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) => {
self.token = Token::new(token::Ident(symbol1, false), ident1_span);
self.token = Token::new(token::Ident(symbol1, IdentIsRaw::No), ident1_span);
// This needs to be `Spacing::Alone` to prevent regressions.
// See issue #76399 and PR #76285 for more details
let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
let base1 =
self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1));
let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
let next_token2 = Token::new(token::Ident(symbol2, IdentIsRaw::No), ident2_span);
self.bump_with((next_token2, self.token_spacing)); // `.`
self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None)
}
@ -1948,7 +1952,7 @@ impl<'a> Parser<'a> {
self.bump(); // `builtin`
self.bump(); // `#`
let Some((ident, false)) = self.token.ident() else {
let Some((ident, IdentIsRaw::No)) = self.token.ident() else {
let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span });
return Err(err);
};
@ -3576,7 +3580,7 @@ impl<'a> Parser<'a> {
fn find_struct_error_after_field_looking_code(&self) -> Option<ExprField> {
match self.token.ident() {
Some((ident, is_raw))
if (is_raw || !ident.is_reserved())
if (matches!(is_raw, IdentIsRaw::Yes) || !ident.is_reserved())
&& self.look_ahead(1, |t| *t == token::Colon) =>
{
Some(ast::ExprField {

View file

@ -3,6 +3,7 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
use crate::errors::{self, MacroExpandsToAdtField};
use crate::fluent_generated as fluent;
use ast::token::IdentIsRaw;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
@ -1079,7 +1080,7 @@ impl<'a> Parser<'a> {
fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
match self.token.ident() {
Some((ident @ Ident { name: kw::Underscore, .. }, false)) => {
Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
self.bump();
Ok(ident)
}
@ -1965,7 +1966,7 @@ impl<'a> Parser<'a> {
let (ident, is_raw) = self.ident_or_err(true)?;
if ident.name == kw::Underscore {
self.sess.gated_spans.gate(sym::unnamed_fields, lo);
} else if !is_raw && ident.is_reserved() {
} else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
let snapshot = self.create_snapshot_for_diagnostic();
let err = if self.check_fn_front_matter(false, Case::Sensitive) {
let inherited_vis = Visibility {
@ -2743,7 +2744,7 @@ impl<'a> Parser<'a> {
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
// Extract an identifier *after* having confirmed that the token is one.
let expect_self_ident = |this: &mut Self| match this.token.ident() {
Some((ident, false)) => {
Some((ident, IdentIsRaw::No)) => {
this.bump();
ident
}

View file

@ -11,6 +11,7 @@ mod stmt;
mod ty;
use crate::lexer::UnmatchedDelim;
use ast::token::IdentIsRaw;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
pub(crate) use expr::ForbiddenLetReason;
@ -499,7 +500,7 @@ impl<'a> Parser<'a> {
fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err(recover)?;
if !is_raw && ident.is_reserved() {
if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
let err = self.expected_ident_found_err();
if recover {
err.emit();
@ -511,7 +512,7 @@ impl<'a> Parser<'a> {
Ok(ident)
}
fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, /* is_raw */ bool)> {
fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, IdentIsRaw)> {
match self.token.ident() {
Some(ident) => Ok(ident),
None => self.expected_ident_found(recover),
@ -568,7 +569,7 @@ impl<'a> Parser<'a> {
}
if case == Case::Insensitive
&& let Some((ident, /* is_raw */ false)) = self.token.ident()
&& let Some((ident, IdentIsRaw::No)) = self.token.ident()
&& ident.as_str().to_lowercase() == kw.as_str().to_lowercase()
{
true
@ -598,7 +599,7 @@ impl<'a> Parser<'a> {
}
if case == Case::Insensitive
&& let Some((ident, /* is_raw */ false)) = self.token.ident()
&& let Some((ident, IdentIsRaw::No)) = self.token.ident()
&& ident.as_str().to_lowercase() == kw.as_str().to_lowercase()
{
self.dcx().emit_err(errors::KwBadCase { span: ident.span, kw: kw.as_str() });

View file

@ -201,6 +201,6 @@ impl<'a> Parser<'a> {
/// The token is an identifier, but not `_`.
/// We prohibit passing `_` to macros expecting `ident` for now.
fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
fn get_macro_ident(token: &Token) -> Option<(Ident, token::IdentIsRaw)> {
token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
}

View file

@ -311,7 +311,7 @@ impl<'a> Parser<'a> {
matches!(
&token.uninterpolate().kind,
token::FatArrow // e.g. `a | => 0,`.
| token::Ident(kw::If, false) // e.g. `a | if expr`.
| token::Ident(kw::If, token::IdentIsRaw::No) // e.g. `a | if expr`.
| token::Eq // e.g. `let a | = 0`.
| token::Semi // e.g. `let a |;`.
| token::Colon // e.g. `let a | :`.

View file

@ -2,6 +2,7 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType};
use crate::errors::PathSingleColon;
use crate::{errors, maybe_whole};
use ast::token::IdentIsRaw;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::{
@ -390,7 +391,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
match self.token.ident() {
Some((ident, false)) if ident.is_path_segment_keyword() => {
Some((ident, IdentIsRaw::No)) if ident.is_path_segment_keyword() => {
self.bump();
Ok(ident)
}

View file

@ -691,7 +691,7 @@ impl<'a> Parser<'a> {
token.kind,
token::Ident(
kw::For | kw::Loop | kw::While,
false
token::IdentIsRaw::No
) | token::OpenDelim(Delimiter::Brace)
)
})