Skip to content

Commit 4a8ccdc

Browse files
committed
Use a fixed-point iteration when breaking tokens
Some tokens need to be broken in a loop until we reach 'unbreakable' tokens.
1 parent 9b2b8a5 commit 4a8ccdc

File tree

5 files changed

+77
-23
lines changed

5 files changed

+77
-23
lines changed

src/librustc_ast/tokenstream.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use rustc_macros::HashStable_Generic;
2121
use rustc_span::{Span, DUMMY_SP};
2222
use smallvec::{smallvec, SmallVec};
2323

24+
use log::debug;
25+
2426
use std::{iter, mem};
2527

2628
/// When the main rust parser encounters a syntax-extension invocation, it
@@ -358,14 +360,47 @@ impl TokenStream {
358360
// leading to some tokens being 'glued' together in one stream but not
359361
// the other. See #68489 for more details.
360362
fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
363+
// In almost all cases, we should have either zero or one levels
364+
// of 'unglueing'. However, in some unusual cases, we may need
365+
// to iterate breaking tokens mutliple times. For example:
366+
// '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
367+
let mut token_trees: SmallVec<[_; 2]>;
361368
if let TokenTree::Token(token) = &tree {
362-
if let Some((first, second)) = token.kind.break_two_token_op() {
363-
return SmallVec::from_buf([TokenTree::Token(Token::new(first, DUMMY_SP)), TokenTree::Token(Token::new(second, DUMMY_SP))]).into_iter()
369+
let mut out = SmallVec::<[_; 2]>::new();
370+
out.push(token.clone());
371+
// Iterate to fixpoint:
372+
// * We start off with 'out' containing our initial token, and `temp` empty
373+
// * If we are able to break any tokens in `out`, then `out` will have
374+
// at least one more element than 'temp', so we will try to break tokens
375+
// again.
376+
// * If we cannot break any tokens in 'out', we are done
377+
loop {
378+
let mut temp = SmallVec::<[_; 2]>::new();
379+
let mut changed = false;
380+
381+
for token in out.into_iter() {
382+
if let Some((first, second)) = token.kind.break_two_token_op() {
383+
temp.push(Token::new(first, DUMMY_SP));
384+
temp.push(Token::new(second, DUMMY_SP));
385+
changed = true;
386+
} else {
387+
temp.push(token);
388+
}
389+
}
390+
out = temp;
391+
if !changed {
392+
break;
393+
}
394+
}
395+
token_trees = out.into_iter().map(|t| TokenTree::Token(t)).collect();
396+
if token_trees.len() != 1 {
397+
debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
364398
}
399+
} else {
400+
token_trees = SmallVec::new();
401+
token_trees.push(tree);
365402
}
366-
let mut vec = SmallVec::<[_; 2]>::new();
367-
vec.push(tree);
368-
vec.into_iter()
403+
token_trees.into_iter()
369404
}
370405

371406
let mut t1 = self.trees().filter(semantic_tree).flat_map(break_tokens);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// aux-build:test-macros.rs
2+
// Regression test for issues #68489 and #70987
3+
// Tests that we properly break tokens in `probably_equal_for_proc_macro`
4+
// See #72306
5+
//
6+
// Note that the weird spacing in this example is critical
7+
// for testing the issue.
8+
9+
extern crate test_macros;
10+
11+
#[test_macros::recollect_attr]
12+
fn repro() {
13+
f :: < Vec < _ > > ( ) ; //~ ERROR cannot find
14+
let a: Option<Option<u8>>= true; //~ ERROR mismatched
15+
}
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0425]: cannot find function `f` in this scope
2+
--> $DIR/break-token-spans.rs:13:5
3+
|
4+
LL | f :: < Vec < _ > > ( ) ;
5+
| ^ not found in this scope
6+
7+
error[E0308]: mismatched types
8+
--> $DIR/break-token-spans.rs:14:32
9+
|
10+
LL | let a: Option<Option<u8>>= true;
11+
| ------------------ ^^^^ expected enum `std::option::Option`, found `bool`
12+
| |
13+
| expected due to this
14+
|
15+
= note: expected enum `std::option::Option<std::option::Option<u8>>`
16+
found type `bool`
17+
18+
error: aborting due to 2 previous errors
19+
20+
Some errors have detailed explanations: E0308, E0425.
21+
For more information about an error, try `rustc --explain E0308`.

src/test/ui/proc-macro/turbo-proc-macro.rs

-9
This file was deleted.

src/test/ui/proc-macro/turbo-proc-macro.stderr

-9
This file was deleted.

0 commit comments

Comments
 (0)