7
7
#![ feature( or_patterns) ]
8
8
9
9
use rustc_ast as ast;
10
- use rustc_ast:: token:: { self , Nonterminal , Token , TokenKind } ;
11
- use rustc_ast:: tokenstream:: { self , TokenStream , TokenTree } ;
10
+ use rustc_ast:: token:: { self , DelimToken , Nonterminal , Token , TokenKind } ;
11
+ use rustc_ast:: tokenstream:: { self , Spacing , 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 } ;
@@ -329,9 +329,8 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
329
329
// modifications, including adding/removing typically non-semantic
330
330
// tokens such as extra braces and commas, don't happen.
331
331
if let Some ( tokens) = tokens {
332
- // If the streams match, then the AST hasn't been modified. Return the captured
333
- // `TokenStream`.
334
- if tokenstream_probably_equal_for_proc_macro ( & tokens, & reparsed_tokens, sess) {
332
+ // Compare with a non-relaxed delim match to start.
333
+ if tokenstream_probably_equal_for_proc_macro ( & tokens, & reparsed_tokens, sess, false ) {
335
334
return tokens;
336
335
}
337
336
@@ -340,23 +339,33 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
340
339
// token stream to match up with inserted parenthesis in the reparsed stream.
341
340
let source_with_parens = pprust:: nonterminal_to_string ( nt) ;
342
341
let filename_with_parens = FileName :: macro_expansion_source_code ( & source_with_parens) ;
343
- let tokens_with_parens = parse_stream_from_source_str (
342
+ let reparsed_tokens_with_parens = parse_stream_from_source_str (
344
343
filename_with_parens,
345
344
source_with_parens,
346
345
sess,
347
346
Some ( span) ,
348
347
) ;
349
348
350
- if tokenstream_probably_equal_for_proc_macro ( & tokens, & tokens_with_parens, sess) {
349
+ // Compare with a relaxed delim match - we want inserted parenthesis in the
350
+ // reparsed stream to match `None`-delimiters in the original stream.
351
+ if tokenstream_probably_equal_for_proc_macro (
352
+ & tokens,
353
+ & reparsed_tokens_with_parens,
354
+ sess,
355
+ true ,
356
+ ) {
351
357
return tokens;
352
358
}
353
359
354
360
info ! (
355
361
"cached tokens found, but they're not \" probably equal\" , \
356
362
going with stringified version"
357
363
) ;
358
- info ! ( "cached tokens: {:?}" , tokens) ;
359
- info ! ( "reparsed tokens: {:?}" , reparsed_tokens) ;
364
+ info ! ( "cached tokens: {}" , pprust:: tts_to_string( & tokens) ) ;
365
+ info ! ( "reparsed tokens: {}" , pprust:: tts_to_string( & reparsed_tokens_with_parens) ) ;
366
+
367
+ info ! ( "cached tokens debug: {:?}" , tokens) ;
368
+ info ! ( "reparsed tokens debug: {:?}" , reparsed_tokens_with_parens) ;
360
369
}
361
370
reparsed_tokens
362
371
}
@@ -370,6 +379,7 @@ pub fn tokenstream_probably_equal_for_proc_macro(
370
379
tokens : & TokenStream ,
371
380
reparsed_tokens : & TokenStream ,
372
381
sess : & ParseSess ,
382
+ relaxed_delim_match : bool ,
373
383
) -> bool {
374
384
// When checking for `probably_eq`, we ignore certain tokens that aren't
375
385
// preserved in the AST. Because they are not preserved, the pretty
@@ -495,7 +505,9 @@ pub fn tokenstream_probably_equal_for_proc_macro(
495
505
let tokens = tokens. trees ( ) . flat_map ( |t| expand_token ( t, sess) ) ;
496
506
let reparsed_tokens = reparsed_tokens. trees ( ) . flat_map ( |t| expand_token ( t, sess) ) ;
497
507
498
- tokens. eq_by ( reparsed_tokens, |t, rt| tokentree_probably_equal_for_proc_macro ( & t, & rt, sess) )
508
+ tokens. eq_by ( reparsed_tokens, |t, rt| {
509
+ tokentree_probably_equal_for_proc_macro ( & t, & rt, sess, relaxed_delim_match)
510
+ } )
499
511
}
500
512
501
513
// See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -507,17 +519,42 @@ pub fn tokentree_probably_equal_for_proc_macro(
507
519
token : & TokenTree ,
508
520
reparsed_token : & TokenTree ,
509
521
sess : & ParseSess ,
522
+ relaxed_delim_match : bool ,
510
523
) -> bool {
511
524
match ( token, reparsed_token) {
512
525
( TokenTree :: Token ( token) , TokenTree :: Token ( reparsed_token) ) => {
513
526
token_probably_equal_for_proc_macro ( token, reparsed_token)
514
527
}
515
- ( TokenTree :: Delimited ( _, delim, tts) , TokenTree :: Delimited ( _, delim2, tts2) ) => {
516
- // `NoDelim` delimiters can appear in the captured tokenstream, but not
517
- // in the reparsed tokenstream. Allow them to match with anything, so
518
- // that we check if the two streams are structurally equivalent.
519
- ( delim == delim2 || * delim == DelimToken :: NoDelim || * delim2 == DelimToken :: NoDelim )
520
- && tokenstream_probably_equal_for_proc_macro ( & tts, & tts2, sess)
528
+ (
529
+ TokenTree :: Delimited ( _, delim, tokens) ,
530
+ TokenTree :: Delimited ( _, reparsed_delim, reparsed_tokens) ,
531
+ ) if delim == reparsed_delim => tokenstream_probably_equal_for_proc_macro (
532
+ tokens,
533
+ reparsed_tokens,
534
+ sess,
535
+ relaxed_delim_match,
536
+ ) ,
537
+ ( TokenTree :: Delimited ( _, DelimToken :: NoDelim , tokens) , reparsed_token) => {
538
+ if relaxed_delim_match {
539
+ if let TokenTree :: Delimited ( _, DelimToken :: Paren , reparsed_tokens) = reparsed_token
540
+ {
541
+ if tokenstream_probably_equal_for_proc_macro (
542
+ tokens,
543
+ reparsed_tokens,
544
+ sess,
545
+ relaxed_delim_match,
546
+ ) {
547
+ return true ;
548
+ }
549
+ }
550
+ }
551
+ tokens. len ( ) == 1
552
+ && tokentree_probably_equal_for_proc_macro (
553
+ & tokens. trees ( ) . next ( ) . unwrap ( ) ,
554
+ reparsed_token,
555
+ sess,
556
+ relaxed_delim_match,
557
+ )
521
558
}
522
559
_ => false ,
523
560
}
0 commit comments