77#![ feature( or_patterns) ]
88
99use 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 } ;
1212use rustc_ast_pretty:: pprust;
1313use rustc_data_structures:: sync:: Lrc ;
1414use rustc_errors:: { Diagnostic , FatalError , Level , PResult } ;
@@ -329,9 +329,8 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
329329 // modifications, including adding/removing typically non-semantic
330330 // tokens such as extra braces and commas, don't happen.
331331 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 ) {
335334 return tokens;
336335 }
337336
@@ -340,23 +339,33 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
340339 // token stream to match up with inserted parenthesis in the reparsed stream.
341340 let source_with_parens = pprust:: nonterminal_to_string ( nt) ;
342341 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 (
344343 filename_with_parens,
345344 source_with_parens,
346345 sess,
347346 Some ( span) ,
348347 ) ;
349348
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+ ) {
351357 return tokens;
352358 }
353359
354360 info ! (
355361 "cached tokens found, but they're not \" probably equal\" , \
356362 going with stringified version"
357363 ) ;
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) ;
360369 }
361370 reparsed_tokens
362371}
@@ -370,6 +379,7 @@ pub fn tokenstream_probably_equal_for_proc_macro(
370379 tokens : & TokenStream ,
371380 reparsed_tokens : & TokenStream ,
372381 sess : & ParseSess ,
382+ relaxed_delim_match : bool ,
373383) -> bool {
374384 // When checking for `probably_eq`, we ignore certain tokens that aren't
375385 // preserved in the AST. Because they are not preserved, the pretty
@@ -495,7 +505,9 @@ pub fn tokenstream_probably_equal_for_proc_macro(
495505 let tokens = tokens. trees ( ) . flat_map ( |t| expand_token ( t, sess) ) ;
496506 let reparsed_tokens = reparsed_tokens. trees ( ) . flat_map ( |t| expand_token ( t, sess) ) ;
497507
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+ } )
499511}
500512
501513// See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -507,17 +519,42 @@ pub fn tokentree_probably_equal_for_proc_macro(
507519 token : & TokenTree ,
508520 reparsed_token : & TokenTree ,
509521 sess : & ParseSess ,
522+ relaxed_delim_match : bool ,
510523) -> bool {
511524 match ( token, reparsed_token) {
512525 ( TokenTree :: Token ( token) , TokenTree :: Token ( reparsed_token) ) => {
513526 token_probably_equal_for_proc_macro ( token, reparsed_token)
514527 }
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+ )
521558 }
522559 _ => false ,
523560 }
0 commit comments