diff options
Diffstat (limited to 'compiler/rustc_expand/src/mbe/macro_rules.rs')
-rw-r--r-- | compiler/rustc_expand/src/mbe/macro_rules.rs | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index e4c65a204..42cc0a6b1 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -223,8 +223,7 @@ fn expand_macro<'cx>( // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. if tts.len() == rhs.tts.len() { - tts = tts.map_enumerated(|i, tt| { - let mut tt = tt.clone(); + tts = tts.map_enumerated_owned(|i, mut tt| { let rhs_tt = &rhs.tts[i]; let ctxt = tt.span().ctxt(); match (&mut tt, rhs_tt) { @@ -535,7 +534,7 @@ pub fn compile_declarative_macro( .pop() .unwrap(); } - sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") + sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") }) .collect::<Vec<mbe::TokenTree>>(), _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"), @@ -628,6 +627,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. } +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 /// tree, because then the matcher would hang indefinitely. fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { @@ -644,16 +677,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { } } TokenTree::Sequence(span, seq) => { - if seq.separator.is_none() - && 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, - }) - { + if is_empty_token_tree(sess, seq) { let sp = span.entire(); sess.span_diagnostic.span_err(sp, "repetition matches empty token tree"); return false; |