From 40512013283da3599e388c6eb38f4016fd8dbeca Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 20 Oct 2022 14:53:59 -0500 Subject: [PATCH] Handle the case where verbatim enters a None group Fixes #1235. As seen in that issue, a syntax node can actually cross the border of a None-delimited group, due to such groups being transparent to the parser in most cases. In the cases that this can occur, the presence of the group is known to be semantically irrelevant, so we just explicitly ignore the presence of the group. It's important that we only ignore None-delimited groups when the verbatim end requires entering the group, as such groups can have semantic impact (such as grouping binary operator chains) in other positions. --- src/verbatim.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/verbatim.rs b/src/verbatim.rs index 0686352f7a..105857d0d7 100644 --- a/src/verbatim.rs +++ b/src/verbatim.rs @@ -1,5 +1,5 @@ use crate::parse::{ParseBuffer, ParseStream}; -use proc_macro2::TokenStream; +use proc_macro2::{Delimiter, TokenStream}; use std::iter; pub fn between<'a>(begin: ParseBuffer<'a>, end: ParseStream<'a>) -> TokenStream { @@ -8,6 +8,22 @@ pub fn between<'a>(begin: ParseBuffer<'a>, end: ParseStream<'a>) -> TokenStream let mut tokens = TokenStream::new(); while cursor != end { let (tt, next) = cursor.token_tree().unwrap(); + + if next > end { + // In some edge cases, a syntax node can actually cross the border + // of a None-delimited group, due to such groups being transparent + // to the parser in most cases. In the cases that this can occur, + // the presence of the group is known to be semantically irrelevant, + // so we should just ignore the presence of the group. (Issue #1235) + if let Some((inside, _span, after)) = cursor.group(Delimiter::None) { + assert!(next == after); + cursor = inside; + continue; + } else { + panic!("verbatim end must not be inside a delimited group"); + } + } + tokens.extend(iter::once(tt)); cursor = next; }