Skip to content

Commit

Permalink
Merge pull request #421 from dtolnay/identunchecked
Browse files Browse the repository at this point in the history
Bypass Ident validation on identifiers created by parser
  • Loading branch information
dtolnay committed Nov 26, 2023
2 parents c513462 + 805a6ad commit 8059195
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
38 changes: 24 additions & 14 deletions src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,22 +755,30 @@ pub(crate) struct Ident {
}

impl Ident {
fn _new(string: &str, raw: bool, span: Span) -> Self {
validate_ident(string, raw);
pub fn new(string: &str, span: Span) -> Self {
validate_ident(string);
Ident::new_unchecked(string, span)
}

pub fn new_unchecked(string: &str, span: Span) -> Self {
Ident {
sym: string.to_owned(),
span,
raw,
raw: false,
}
}

pub fn new(string: &str, span: Span) -> Self {
Ident::_new(string, false, span)
pub fn new_raw(string: &str, span: Span) -> Self {
validate_ident_raw(string);
Ident::new_raw_unchecked(string, span)
}

pub fn new_raw(string: &str, span: Span) -> Self {
Ident::_new(string, true, span)
pub fn new_raw_unchecked(string: &str, span: Span) -> Self {
Ident {
sym: string.to_owned(),
span,
raw: true,
}
}

pub fn span(&self) -> Span {
Expand All @@ -790,7 +798,7 @@ pub(crate) fn is_ident_continue(c: char) -> bool {
unicode_ident::is_xid_continue(c)
}

fn validate_ident(string: &str, raw: bool) {
fn validate_ident(string: &str) {
if string.is_empty() {
panic!("Ident is not allowed to be empty; use Option<Ident>");
}
Expand All @@ -816,14 +824,16 @@ fn validate_ident(string: &str, raw: bool) {
if !ident_ok(string) {
panic!("{:?} is not a valid Ident", string);
}
}

if raw {
match string {
"_" | "super" | "self" | "Self" | "crate" => {
panic!("`r#{}` cannot be a raw identifier", string);
}
_ => {}
fn validate_ident_raw(string: &str) {
validate_ident(string);

match string {
"_" | "super" | "self" | "Self" | "crate" => {
panic!("`r#{}` cannot be a raw identifier", string);
}
_ => {}
}
}

Expand Down
19 changes: 13 additions & 6 deletions src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::fallback::{
is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream,
self, is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream,
TokenStreamBuilder,
};
use crate::{Delimiter, Punct, Spacing, TokenTree};
Expand Down Expand Up @@ -300,7 +300,10 @@ fn ident_any(input: Cursor) -> PResult<crate::Ident> {
let (rest, sym) = ident_not_raw(rest)?;

if !raw {
let ident = crate::Ident::new(sym, crate::Span::call_site());
let ident = crate::Ident::_new(crate::imp::Ident::new_unchecked(
sym,
fallback::Span::call_site(),
));
return Ok((rest, ident));
}

Expand All @@ -309,7 +312,10 @@ fn ident_any(input: Cursor) -> PResult<crate::Ident> {
_ => {}
}

let ident = crate::Ident::new_raw(sym, crate::Span::call_site());
let ident = crate::Ident::_new(crate::imp::Ident::new_raw_unchecked(
sym,
fallback::Span::call_site(),
));
Ok((rest, ident))
}

Expand Down Expand Up @@ -908,12 +914,13 @@ fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult
#[cfg(span_locations)]
let lo = input.off;
let (rest, (comment, inner)) = doc_comment_contents(input)?;
let span = crate::Span::_new_fallback(Span {
let fallback_span = Span {
#[cfg(span_locations)]
lo,
#[cfg(span_locations)]
hi: rest.off,
});
};
let span = crate::Span::_new_fallback(fallback_span);

let mut scan_for_bare_cr = comment;
while let Some(cr) = scan_for_bare_cr.find('\r') {
Expand All @@ -934,7 +941,7 @@ fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult
trees.push_token_from_parser(TokenTree::Punct(bang));
}

let doc_ident = crate::Ident::new("doc", span);
let doc_ident = crate::Ident::_new(crate::imp::Ident::new_unchecked("doc", fallback_span));
let mut equal = Punct::new('=', Spacing::Alone);
equal.set_span(span);
let mut literal = crate::Literal::string(comment);
Expand Down
8 changes: 8 additions & 0 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,13 +646,21 @@ impl Ident {
}
}

pub fn new_unchecked(string: &str, span: fallback::Span) -> Self {
Ident::Fallback(fallback::Ident::new_unchecked(string, span))
}

pub fn new_raw(string: &str, span: Span) -> Self {
match span {
Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)),
Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)),
}
}

pub fn new_raw_unchecked(string: &str, span: fallback::Span) -> Self {
Ident::Fallback(fallback::Ident::new_raw_unchecked(string, span))
}

pub fn span(&self) -> Span {
match self {
Ident::Compiler(t) => Span::Compiler(t.span()),
Expand Down

0 comments on commit 8059195

Please sign in to comment.