Skip to content

Commit 7300bd6

Browse files
committed
Move the missing fragment identifier checking.
In #95555 this was moved out of `parse_tt_inner` and `nameize` into `compute_locs`. But the next commit will be moving `compute_locs` outwards to a place that isn't suitable for the missing fragment identifier checking. So this reinstates the old checking.
1 parent 896d8f5 commit 7300bd6

File tree

1 file changed

+58
-47
lines changed

1 file changed

+58
-47
lines changed

compiler/rustc_expand/src/mbe/macro_parser.rs

+58-47
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ enum MatcherLoc {
131131
MetaVarDecl {
132132
span: Span,
133133
bind: Ident,
134-
kind: NonterminalKind,
134+
kind: Option<NonterminalKind>,
135135
next_metavar: usize,
136136
seq_depth: usize,
137137
},
@@ -337,26 +337,22 @@ impl TtParser {
337337
/// recursive. This conversion is fairly cheap and the representation is sufficiently better
338338
/// for matching than `&[TokenTree]` that it's a clear performance win even with the overhead.
339339
/// But it might be possible to move the conversion outwards so it only occurs once per macro.
340-
fn compute_locs(
341-
&mut self,
342-
sess: &ParseSess,
343-
matcher: &[TokenTree],
344-
) -> Result<usize, (Span, String)> {
340+
fn compute_locs(&mut self, sess: &ParseSess, matcher: &[TokenTree]) -> usize {
345341
fn inner(
346342
sess: &ParseSess,
347343
tts: &[TokenTree],
348344
locs: &mut Vec<MatcherLoc>,
349345
next_metavar: &mut usize,
350346
seq_depth: usize,
351-
) -> Result<(), (Span, String)> {
347+
) {
352348
for tt in tts {
353349
match tt {
354350
TokenTree::Token(token) => {
355351
locs.push(MatcherLoc::Token { token: token.clone() });
356352
}
357353
TokenTree::Delimited(_, delimited) => {
358354
locs.push(MatcherLoc::Delimited);
359-
inner(sess, &delimited.all_tts, locs, next_metavar, seq_depth)?;
355+
inner(sess, &delimited.all_tts, locs, next_metavar, seq_depth);
360356
}
361357
TokenTree::Sequence(_, seq) => {
362358
// We can't determine `idx_first_after` and construct the final
@@ -370,7 +366,7 @@ impl TtParser {
370366
let op = seq.kleene.op;
371367
let idx_first = locs.len();
372368
let idx_seq = idx_first - 1;
373-
inner(sess, &seq.tts, locs, next_metavar, seq_depth + 1)?;
369+
inner(sess, &seq.tts, locs, next_metavar, seq_depth + 1);
374370

375371
if let Some(separator) = &seq.separator {
376372
locs.push(MatcherLoc::SequenceSep { separator: separator.clone() });
@@ -389,40 +385,29 @@ impl TtParser {
389385
};
390386
}
391387
&TokenTree::MetaVarDecl(span, bind, kind) => {
392-
if let Some(kind) = kind {
393-
locs.push(MatcherLoc::MetaVarDecl {
394-
span,
395-
bind,
396-
kind,
397-
next_metavar: *next_metavar,
398-
seq_depth,
399-
});
400-
*next_metavar += 1;
401-
} else if sess
402-
.missing_fragment_specifiers
403-
.borrow_mut()
404-
.remove(&span)
405-
.is_some()
406-
{
407-
// E.g. `$e` instead of `$e:expr`.
408-
return Err((span, "missing fragment specifier".to_string()));
409-
}
388+
locs.push(MatcherLoc::MetaVarDecl {
389+
span,
390+
bind,
391+
kind,
392+
next_metavar: *next_metavar,
393+
seq_depth,
394+
});
395+
*next_metavar += 1;
410396
}
411397
TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
412398
}
413399
}
414-
Ok(())
415400
}
416401

417402
self.locs.clear();
418403
let mut next_metavar = 0;
419-
inner(sess, matcher, &mut self.locs, &mut next_metavar, /* seq_depth */ 0)?;
404+
inner(sess, matcher, &mut self.locs, &mut next_metavar, /* seq_depth */ 0);
420405

421406
// A final entry is needed for eof.
422407
self.locs.push(MatcherLoc::Eof);
423408

424409
// This is the number of metavar decls.
425-
Ok(next_metavar)
410+
next_metavar
426411
}
427412

428413
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -434,6 +419,7 @@ impl TtParser {
434419
/// track of through the mps generated.
435420
fn parse_tt_inner(
436421
&mut self,
422+
sess: &ParseSess,
437423
num_metavar_decls: usize,
438424
token: &Token,
439425
) -> Option<NamedParseResult> {
@@ -532,12 +518,20 @@ impl TtParser {
532518
mp.idx = idx_first;
533519
self.cur_mps.push(mp);
534520
}
535-
MatcherLoc::MetaVarDecl { kind, .. } => {
521+
&MatcherLoc::MetaVarDecl { span, kind, .. } => {
536522
// Built-in nonterminals never start with these tokens, so we can eliminate
537523
// them from consideration. We use the span of the metavariable declaration
538524
// to determine any edition-specific matching behavior for non-terminals.
539-
if Parser::nonterminal_may_begin_with(*kind, token) {
540-
self.bb_mps.push(mp);
525+
if let Some(kind) = kind {
526+
if Parser::nonterminal_may_begin_with(kind, token) {
527+
self.bb_mps.push(mp);
528+
}
529+
} else {
530+
// Both this check and the one in `nameize` are necessary, surprisingly.
531+
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
532+
// E.g. `$e` instead of `$e:expr`.
533+
return Some(Error(span, "missing fragment specifier".to_string()));
534+
}
541535
}
542536
}
543537
MatcherLoc::Eof => {
@@ -564,7 +558,7 @@ impl TtParser {
564558
// Need to take ownership of the matches from within the `Lrc`.
565559
Lrc::make_mut(&mut eof_mp.matches);
566560
let matches = Lrc::try_unwrap(eof_mp.matches).unwrap().into_iter();
567-
self.nameize(matches)
561+
self.nameize(sess, matches)
568562
}
569563
EofMatcherPositions::Multiple => {
570564
Error(token.span, "ambiguity: multiple successful parses".to_string())
@@ -588,10 +582,7 @@ impl TtParser {
588582
parser: &mut Cow<'_, Parser<'_>>,
589583
matcher: &[TokenTree],
590584
) -> NamedParseResult {
591-
let num_metavar_decls = match self.compute_locs(parser.sess, matcher) {
592-
Ok(num_metavar_decls) => num_metavar_decls,
593-
Err((span, msg)) => return Error(span, msg),
594-
};
585+
let num_metavar_decls = self.compute_locs(parser.sess, matcher);
595586

596587
// A queue of possible matcher positions. We initialize it with the matcher position in
597588
// which the "dot" is before the first token of the first token tree in `matcher`.
@@ -607,7 +598,7 @@ impl TtParser {
607598

608599
// Process `cur_mps` until either we have finished the input or we need to get some
609600
// parsing from the black-box parser done.
610-
if let Some(res) = self.parse_tt_inner(num_metavar_decls, &parser.token) {
601+
if let Some(res) = self.parse_tt_inner(&parser.sess, num_metavar_decls, &parser.token) {
611602
return res;
612603
}
613604

@@ -637,7 +628,11 @@ impl TtParser {
637628
let mut mp = self.bb_mps.pop().unwrap();
638629
let loc = &self.locs[mp.idx];
639630
if let &MatcherLoc::MetaVarDecl {
640-
span, kind, next_metavar, seq_depth, ..
631+
span,
632+
kind: Some(kind),
633+
next_metavar,
634+
seq_depth,
635+
..
641636
} = loc
642637
{
643638
// We use the span of the metavariable declaration to determine any
@@ -682,7 +677,9 @@ impl TtParser {
682677
.bb_mps
683678
.iter()
684679
.map(|mp| match &self.locs[mp.idx] {
685-
MatcherLoc::MetaVarDecl { bind, kind, .. } => format!("{} ('{}')", kind, bind),
680+
MatcherLoc::MetaVarDecl { bind, kind: Some(kind), .. } => {
681+
format!("{} ('{}')", kind, bind)
682+
}
686683
_ => unreachable!(),
687684
})
688685
.collect::<Vec<String>>()
@@ -702,16 +699,30 @@ impl TtParser {
702699
)
703700
}
704701

705-
fn nameize<I: Iterator<Item = NamedMatch>>(&self, mut res: I) -> NamedParseResult {
702+
fn nameize<I: Iterator<Item = NamedMatch>>(
703+
&self,
704+
sess: &ParseSess,
705+
mut res: I,
706+
) -> NamedParseResult {
706707
// Make that each metavar has _exactly one_ binding. If so, insert the binding into the
707708
// `NamedParseResult`. Otherwise, it's an error.
708709
let mut ret_val = FxHashMap::default();
709710
for loc in self.locs.iter() {
710-
if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc {
711-
match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) {
712-
Vacant(spot) => spot.insert(res.next().unwrap()),
713-
Occupied(..) => return Error(span, format!("duplicated bind name: {}", bind)),
714-
};
711+
if let &MatcherLoc::MetaVarDecl { span, bind, kind, .. } = loc {
712+
if kind.is_some() {
713+
match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) {
714+
Vacant(spot) => spot.insert(res.next().unwrap()),
715+
Occupied(..) => {
716+
return Error(span, format!("duplicated bind name: {}", bind));
717+
}
718+
};
719+
} else {
720+
// Both this check and the one in `parse_tt_inner` are necessary, surprisingly.
721+
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
722+
// E.g. `$e` instead of `$e:expr`.
723+
return Error(span, "missing fragment specifier".to_string());
724+
}
725+
}
715726
}
716727
}
717728
Success(ret_val)

0 commit comments

Comments
 (0)