summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_expand/src/mbe/macro_rules.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_expand/src/mbe/macro_rules.rs')
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs50
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;