Skip to content

Commit 142f10b

Browse files
authored
Merge pull request #514 from dtolnay/rawlifetime
Reject 'prefix#lifetime
2 parents be64a30 + 1c35895 commit 142f10b

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/parse.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,10 @@ fn digits(mut input: Cursor) -> Result<Cursor, Reject> {
871871
fn punct(input: Cursor) -> PResult<Punct> {
872872
let (rest, ch) = punct_char(input)?;
873873
if ch == '\'' {
874-
if ident_any(rest)?.0.starts_with_char('\'') {
874+
let (after_lifetime, _ident) = ident_any(rest)?;
875+
if after_lifetime.starts_with_char('\'')
876+
|| (after_lifetime.starts_with_char('#') && !rest.starts_with("r#"))
877+
{
875878
Err(Reject)
876879
} else {
877880
Ok((rest, Punct::new('\'', Spacing::Joint)))

tests/test.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,81 @@ fn source_text() {
453453
assert_eq!("a", second.span().source_text().unwrap());
454454
}
455455

456+
#[test]
457+
fn lifetimes() {
458+
let mut tokens = "'a 'static 'struct 'r#gen 'r#prefix#lifetime"
459+
.parse::<TokenStream>()
460+
.unwrap()
461+
.into_iter();
462+
assert!(match tokens.next() {
463+
Some(TokenTree::Punct(punct)) => {
464+
punct.as_char() == '\'' && punct.spacing() == Spacing::Joint
465+
}
466+
_ => false,
467+
});
468+
assert!(match tokens.next() {
469+
Some(TokenTree::Ident(ident)) => ident == "a",
470+
_ => false,
471+
});
472+
assert!(match tokens.next() {
473+
Some(TokenTree::Punct(punct)) => {
474+
punct.as_char() == '\'' && punct.spacing() == Spacing::Joint
475+
}
476+
_ => false,
477+
});
478+
assert!(match tokens.next() {
479+
Some(TokenTree::Ident(ident)) => ident == "static",
480+
_ => false,
481+
});
482+
assert!(match tokens.next() {
483+
Some(TokenTree::Punct(punct)) => {
484+
punct.as_char() == '\'' && punct.spacing() == Spacing::Joint
485+
}
486+
_ => false,
487+
});
488+
assert!(match tokens.next() {
489+
Some(TokenTree::Ident(ident)) => ident == "struct",
490+
_ => false,
491+
});
492+
assert!(match tokens.next() {
493+
Some(TokenTree::Punct(punct)) => {
494+
punct.as_char() == '\'' && punct.spacing() == Spacing::Joint
495+
}
496+
_ => false,
497+
});
498+
assert!(match tokens.next() {
499+
Some(TokenTree::Ident(ident)) => ident == "r#gen",
500+
_ => false,
501+
});
502+
assert!(match tokens.next() {
503+
Some(TokenTree::Punct(punct)) => {
504+
punct.as_char() == '\'' && punct.spacing() == Spacing::Joint
505+
}
506+
_ => false,
507+
});
508+
assert!(match tokens.next() {
509+
Some(TokenTree::Ident(ident)) => ident == "r#prefix",
510+
_ => false,
511+
});
512+
assert!(match tokens.next() {
513+
Some(TokenTree::Punct(punct)) => {
514+
punct.as_char() == '#' && punct.spacing() == Spacing::Alone
515+
}
516+
_ => false,
517+
});
518+
assert!(match tokens.next() {
519+
Some(TokenTree::Ident(ident)) => ident == "lifetime",
520+
_ => false,
521+
});
522+
523+
"' a".parse::<TokenStream>().unwrap_err();
524+
"' r#gen".parse::<TokenStream>().unwrap_err();
525+
"' prefix#lifetime".parse::<TokenStream>().unwrap_err();
526+
"'prefix#lifetime".parse::<TokenStream>().unwrap_err();
527+
"'aa'bb".parse::<TokenStream>().unwrap_err();
528+
"'r#gen'a".parse::<TokenStream>().unwrap_err();
529+
}
530+
456531
#[test]
457532
fn roundtrip() {
458533
fn roundtrip(p: &str) {

0 commit comments

Comments
 (0)