diff options
| author | Julien Cretin <cretin@google.com> | 2019-07-24 23:32:26 +0200 |
|---|---|---|
| committer | Julien Cretin <cretin@google.com> | 2019-07-25 23:28:47 +0200 |
| commit | df4b23e7212b8f7a3f62f469f666021226e29c17 (patch) | |
| tree | 8f4914767734381100b154b1a33f802727d04271 /src/libsyntax | |
| parent | eedf6ce4ef54bb03818ab21d714f1b9f13a6b31c (diff) | |
| download | rust-df4b23e7212b8f7a3f62f469f666021226e29c17.tar.gz rust-df4b23e7212b8f7a3f62f469f666021226e29c17.zip | |
Implement slow-path for FirstSets::first
When 2 or more sequences share the same span, we can't use the precomputed map for their first set. So we compute it recursively. Fixes #62831.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4503cea0f10..1731c0f713b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -625,38 +625,37 @@ impl FirstSets { return first; } TokenTree::Sequence(sp, ref seq_rep) => { - match self.first.get(&sp.entire()) { - Some(&Some(ref subfirst)) => { - // If the sequence contents can be empty, then the first - // token could be the separator token itself. - - if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TokenTree::Token(sep.clone())); - } - - assert!(first.maybe_empty); - first.add_all(subfirst); - if subfirst.maybe_empty - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne - { - // continue scanning for more first - // tokens, but also make sure we - // restore empty-tracking state - first.maybe_empty = true; - continue; - } else { - return first; - } - } - + let subfirst_owned; + let subfirst = match self.first.get(&sp.entire()) { + Some(&Some(ref subfirst)) => subfirst, Some(&None) => { - panic!("assume all sequences have (unique) spans for now"); + subfirst_owned = self.first(&seq_rep.tts[..]); + &subfirst_owned } - None => { panic!("We missed a sequence during FirstSets construction"); } + }; + + // If the sequence contents can be empty, then the first + // token could be the separator token itself. + if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { + first.add_one_maybe(TokenTree::Token(sep.clone())); + } + + assert!(first.maybe_empty); + first.add_all(subfirst); + if subfirst.maybe_empty + || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne + { + // Continue scanning for more first + // tokens, but also make sure we + // restore empty-tracking state. + first.maybe_empty = true; + continue; + } else { + return first; } } } |
