|
8 | 8 |
|
9 | 9 | use rustc_ast as ast; |
10 | 10 | use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; |
11 | | -use rustc_ast::tokenstream::{self, Spacing, TokenStream, TokenTree}; |
| 11 | +use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; |
12 | 12 | use rustc_ast_pretty::pprust; |
13 | 13 | use rustc_data_structures::sync::Lrc; |
14 | 14 | use rustc_errors::{Diagnostic, FatalError, Level, PResult}; |
@@ -435,31 +435,42 @@ pub fn tokenstream_probably_equal_for_proc_macro( |
435 | 435 | token_trees.into_iter() |
436 | 436 | } |
437 | 437 |
|
438 | | - let expand_nt = |tree: TokenTree| { |
439 | | - if let TokenTree::Token(Token { kind: TokenKind::Interpolated(nt), span }) = &tree { |
440 | | - // When checking tokenstreams for 'probable equality', we are comparing |
441 | | - // a captured (from parsing) `TokenStream` to a reparsed tokenstream. |
442 | | - // The reparsed Tokenstream will never have `None`-delimited groups, |
443 | | - // since they are only ever inserted as a result of macro expansion. |
444 | | - // Therefore, inserting a `None`-delimtied group here (when we |
445 | | - // convert a nested `Nonterminal` to a tokenstream) would cause |
446 | | - // a mismatch with the reparsed tokenstream. |
447 | | - // |
448 | | - // Note that we currently do not handle the case where the |
449 | | - // reparsed stream has a `Parenthesis`-delimited group |
450 | | - // inserted. This will cause a spurious mismatch: |
451 | | - // issue #75734 tracks resolving this. |
452 | | - nt_to_tokenstream(nt, sess, *span).into_trees() |
453 | | - } else { |
454 | | - TokenStream::new(vec![(tree, Spacing::Alone)]).into_trees() |
455 | | - } |
456 | | - }; |
| 438 | + fn expand_token(tree: TokenTree, sess: &ParseSess) -> impl Iterator<Item = TokenTree> { |
| 439 | + // When checking tokenstreams for 'probable equality', we are comparing |
| 440 | + // a captured (from parsing) `TokenStream` to a reparsed tokenstream. |
| 441 | + // The reparsed Tokenstream will never have `None`-delimited groups, |
| 442 | + // since they are only ever inserted as a result of macro expansion. |
| 443 | + // Therefore, inserting a `None`-delimtied group here (when we |
| 444 | + // convert a nested `Nonterminal` to a tokenstream) would cause |
| 445 | + // a mismatch with the reparsed tokenstream. |
| 446 | + // |
| 447 | + // Note that we currently do not handle the case where the |
| 448 | + // reparsed stream has a `Parenthesis`-delimited group |
| 449 | + // inserted. This will cause a spurious mismatch: |
| 450 | + // issue #75734 tracks resolving this. |
| 451 | + |
| 452 | + let expanded: SmallVec<[_; 1]> = |
| 453 | + if let TokenTree::Token(Token { kind: TokenKind::Interpolated(nt), span }) = &tree { |
| 454 | + nt_to_tokenstream(nt, sess, *span) |
| 455 | + .into_trees() |
| 456 | + .flat_map(|t| expand_token(t, sess)) |
| 457 | + .collect() |
| 458 | + } else { |
| 459 | + // Filter before and after breaking tokens, |
| 460 | + // since we may want to ignore both glued and unglued tokens. |
| 461 | + std::iter::once(tree) |
| 462 | + .filter(semantic_tree) |
| 463 | + .flat_map(break_tokens) |
| 464 | + .filter(semantic_tree) |
| 465 | + .collect() |
| 466 | + }; |
| 467 | + expanded.into_iter() |
| 468 | + } |
457 | 469 |
|
458 | 470 | // Break tokens after we expand any nonterminals, so that we break tokens |
459 | 471 | // that are produced as a result of nonterminal expansion. |
460 | | - let tokens = tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens); |
461 | | - let reparsed_tokens = |
462 | | - reparsed_tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens); |
| 472 | + let tokens = tokens.trees().flat_map(|t| expand_token(t, sess)); |
| 473 | + let reparsed_tokens = reparsed_tokens.trees().flat_map(|t| expand_token(t, sess)); |
463 | 474 |
|
464 | 475 | tokens.eq_by(reparsed_tokens, |t, rt| tokentree_probably_equal_for_proc_macro(&t, &rt, sess)) |
465 | 476 | } |
|
0 commit comments