Rollup merge of #112345 - bvanjoi:fix-112342, r=nilstrieb,est31
fix(expand): prevent infinity loop in macro containing only "///" Fixes https://github.com/rust-lang/rust/issues/112342 Issue #112342 was caused by an infinity loop in `parse_tt_inner`, and the state of it is as follows: - `matcher`: `[Sequence, Token(Doc), SequenceKleeneOpNoSep(op: ZeroOrMore), Eof]` - loop: | Iteration | Action | | - | - | | 0 | enter `Sequence`| | 1 | enter `Token(Doc)` and `mp.idx += 1` had been executed | | 2 | enter `SequenceKleeneOpNoSep` and reset `mp.idx` to `1` | | 3 | enter `Token(Doc)` again| To prevent the infinite loop, a check for whether it only contains `DocComment` in `check_lhs_no_empty_seq` had been added.
This commit is contained in:
commit
42cf6da6af
6 changed files with 212 additions and 10 deletions
|
@ -249,6 +249,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single matcher position, representing the state of matching.
|
/// A single matcher position, representing the state of matching.
|
||||||
|
#[derive(Debug)]
|
||||||
struct MatcherPos {
|
struct MatcherPos {
|
||||||
/// The index into `TtParser::locs`, which represents the "dot".
|
/// The index into `TtParser::locs`, which represents the "dot".
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
|
|
@ -628,6 +628,40 @@ fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree)
|
||||||
// after parsing/expansion. we can report every error in every macro this way.
|
// after parsing/expansion. we can report every error in every macro this way.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool {
|
||||||
|
if seq.separator.is_some() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let mut is_empty = true;
|
||||||
|
let mut iter = seq.tts.iter().peekable();
|
||||||
|
while let Some(tt) = iter.next() {
|
||||||
|
match tt {
|
||||||
|
mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => {}
|
||||||
|
mbe::TokenTree::Token(t @ Token { kind: DocComment(..), .. }) => {
|
||||||
|
let mut now = t;
|
||||||
|
while let Some(&mbe::TokenTree::Token(
|
||||||
|
next @ Token { kind: DocComment(..), .. },
|
||||||
|
)) = iter.peek()
|
||||||
|
{
|
||||||
|
now = next;
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
let span = t.span.to(now.span);
|
||||||
|
sess.span_diagnostic.span_note_without_error(
|
||||||
|
span,
|
||||||
|
"doc comments are ignored in matcher position",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
mbe::TokenTree::Sequence(_, sub_seq)
|
||||||
|
if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
|
||||||
|
|| sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne) => {}
|
||||||
|
_ => is_empty = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks that the lhs contains no repetition which could match an empty token
|
/// Checks that the lhs contains no repetition which could match an empty token
|
||||||
/// tree, because then the matcher would hang indefinitely.
|
/// tree, because then the matcher would hang indefinitely.
|
||||||
fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
||||||
|
@ -644,16 +678,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenTree::Sequence(span, seq) => {
|
TokenTree::Sequence(span, seq) => {
|
||||||
if seq.separator.is_none()
|
if is_empty_token_tree(sess, seq) {
|
||||||
&& seq.tts.iter().all(|seq_tt| match seq_tt {
|
|
||||||
TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => true,
|
|
||||||
TokenTree::Sequence(_, sub_seq) => {
|
|
||||||
sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
|
|
||||||
|| sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let sp = span.entire();
|
let sp = span.entire();
|
||||||
sess.span_diagnostic.span_err(sp, "repetition matches empty token tree");
|
sess.span_diagnostic.span_err(sp, "repetition matches empty token tree");
|
||||||
return false;
|
return false;
|
||||||
|
|
49
tests/ui/macros/issue-112342-1.rs
Normal file
49
tests/ui/macros/issue-112342-1.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// same as #95267, ignore doc comment although it's a bug.
|
||||||
|
|
||||||
|
macro_rules! m1 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
)*
|
||||||
|
//~^^^ERROR repetition matches empty token tree
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m1! {}
|
||||||
|
|
||||||
|
macro_rules! m2 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
)+
|
||||||
|
//~^^^ERROR repetition matches empty token tree
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m2! {}
|
||||||
|
|
||||||
|
macro_rules! m3 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
)?
|
||||||
|
//~^^^ERROR repetition matches empty token tree
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m3! {}
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! m4 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
///
|
||||||
|
)*
|
||||||
|
//~^^^^ERROR repetition matches empty token tree
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m4! {}
|
||||||
|
|
||||||
|
fn main() {}
|
64
tests/ui/macros/issue-112342-1.stderr
Normal file
64
tests/ui/macros/issue-112342-1.stderr
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-1.rs:6:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-112342-1.rs:5:10
|
||||||
|
|
|
||||||
|
LL | $(
|
||||||
|
| __________^
|
||||||
|
LL | | ///
|
||||||
|
LL | | )*
|
||||||
|
| |_________^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-1.rs:17:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-112342-1.rs:16:10
|
||||||
|
|
|
||||||
|
LL | $(
|
||||||
|
| __________^
|
||||||
|
LL | | ///
|
||||||
|
LL | | )+
|
||||||
|
| |_________^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-1.rs:28:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-112342-1.rs:27:10
|
||||||
|
|
|
||||||
|
LL | $(
|
||||||
|
| __________^
|
||||||
|
LL | | ///
|
||||||
|
LL | | )?
|
||||||
|
| |_________^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-1.rs:40:13
|
||||||
|
|
|
||||||
|
LL | / ///
|
||||||
|
LL | | ///
|
||||||
|
| |_______________^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-112342-1.rs:39:10
|
||||||
|
|
|
||||||
|
LL | $(
|
||||||
|
| __________^
|
||||||
|
LL | | ///
|
||||||
|
LL | | ///
|
||||||
|
LL | | )*
|
||||||
|
| |_________^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
39
tests/ui/macros/issue-112342-2.rs
Normal file
39
tests/ui/macros/issue-112342-2.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
// same as #95267, ignore doc comment although it's a bug.
|
||||||
|
|
||||||
|
macro_rules! m1 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
$expr: expr,
|
||||||
|
)*
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m1! {}
|
||||||
|
|
||||||
|
macro_rules! m2 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
$expr: expr,
|
||||||
|
///
|
||||||
|
)*
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m2! {}
|
||||||
|
|
||||||
|
macro_rules! m3 {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
///
|
||||||
|
$tt: tt,
|
||||||
|
)*
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m3! {}
|
||||||
|
|
||||||
|
fn main() {}
|
24
tests/ui/macros/issue-112342-2.stderr
Normal file
24
tests/ui/macros/issue-112342-2.stderr
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-2.rs:8:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-2.rs:19:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-2.rs:21:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
note: doc comments are ignored in matcher position
|
||||||
|
--> $DIR/issue-112342-2.rs:31:13
|
||||||
|
|
|
||||||
|
LL | ///
|
||||||
|
| ^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue