@@ -301,8 +301,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
301301
302302    let  filename = FileName :: anon_source_code ( & wrapped_source) ; 
303303
304-     // Any errors in parsing should also appear when the doctest is compiled for real, so just 
305-     // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. 
306304    let  sm = Arc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ; 
307305    let  fallback_bundle = rustc_errors:: fallback_fluent_bundle ( 
308306        rustc_driver:: DEFAULT_LOCALE_RESOURCES . to_vec ( ) , 
@@ -311,7 +309,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
311309    info. supports_color  =
312310        HumanEmitter :: new ( stderr_destination ( ColorConfig :: Auto ) ,  fallback_bundle. clone ( ) ) 
313311            . supports_color ( ) ; 
314- 
312+     // Any errors in parsing should also appear when the doctest is compiled for real, so just 
313+     // send all the errors that the parser emits directly into a `Sink` instead of stderr. 
315314    let  emitter = HumanEmitter :: new ( Box :: new ( io:: sink ( ) ) ,  fallback_bundle) ; 
316315
317316    // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser 
@@ -339,9 +338,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
339338        * prev_span_hi = hi; 
340339    } 
341340
342-     // Recurse through functions body. It is necessary because the doctest source code is 
343-     // wrapped in a function to limit the number of AST errors. If we don't recurse into 
344-     // functions, we would thing all top-level items (so basically nothing). 
345341    fn  check_item ( item :  & ast:: Item ,  info :  & mut  ParseSourceInfo ,  crate_name :  & Option < & str > )  -> bool  { 
346342        let  mut  is_extern_crate = false ; 
347343        if  !info. has_global_allocator 
@@ -351,8 +347,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
351347        } 
352348        match  item. kind  { 
353349            ast:: ItemKind :: Fn ( ref  fn_item)  if  !info. has_main_fn  => { 
354-                 // We only push if it's the top item because otherwise, we would duplicate 
355-                 // its content since the top-level item was already added. 
356350                if  fn_item. ident . name  == sym:: main { 
357351                    info. has_main_fn  = true ; 
358352                } 
@@ -412,44 +406,41 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
412406                let  mut  is_extern_crate = false ; 
413407                match  stmt. kind  { 
414408                    StmtKind :: Item ( ref  item)  => { 
415-                         is_extern_crate = check_item ( & item,  & mut  info,  crate_name) ; 
416-                     } 
417-                     StmtKind :: Expr ( ref  expr)  => { 
418-                         if  matches ! ( expr. kind,  ast:: ExprKind :: Err ( _) )  { 
419-                             reset_error_count ( & psess) ; 
420-                             return  Err ( ( ) ) ; 
421-                         } 
422-                         has_non_items = true ; 
409+                         is_extern_crate = check_item ( item,  & mut  info,  crate_name) ; 
423410                    } 
424411                    // We assume that the macro calls will expand to item(s) even though they could 
425-                     // expand to statements and expressions. And the simple fact that we're trying 
426-                     // to retrieve a `main` function inside it is a terrible idea. 
412+                     // expand to statements and expressions. 
427413                    StmtKind :: MacCall ( ref  mac_call)  => { 
428-                         if  info. has_main_fn  { 
429-                             continue ; 
430-                         } 
431-                         let  mut  iter = mac_call. mac . args . tokens . iter ( ) ; 
432- 
433-                         while  let  Some ( token)  = iter. next ( )  { 
434-                             if  let  TokenTree :: Token ( token,  _)  = token
435-                                 && let  TokenKind :: Ident ( name,  _)  = token. kind 
436-                                 && name == kw:: Fn 
437-                                 && let  Some ( TokenTree :: Token ( fn_token,  _) )  = iter. peek ( ) 
438-                                 && let  TokenKind :: Ident ( fn_name,  _)  = fn_token. kind 
439-                                 && fn_name == sym:: main
440-                                 && let  Some ( TokenTree :: Delimited ( _,  _,  Delimiter :: Parenthesis ,  _) )  = { 
441-                                     iter. next ( ) ; 
442-                                     iter. peek ( ) 
414+                         if  !info. has_main_fn  { 
415+                             // For backward compatibility, we look for the token sequence `fn main(…)` 
416+                             // in the macro input (!) to crudely detect main functions "masked by a 
417+                             // wrapper macro". For the record, this is a horrible heuristic! 
418+                             // See <https://github.com/rust-lang/rust/issues/56898>. 
419+                             let  mut  iter = mac_call. mac . args . tokens . iter ( ) ; 
420+                             while  let  Some ( token)  = iter. next ( )  { 
421+                                 if  let  TokenTree :: Token ( token,  _)  = token
422+                                     && let  TokenKind :: Ident ( kw:: Fn ,  _)  = token. kind 
423+                                     && let  Some ( TokenTree :: Token ( ident,  _) )  = iter. peek ( ) 
424+                                     && let  TokenKind :: Ident ( sym:: main,  _)  = ident. kind 
425+                                     && let  Some ( TokenTree :: Delimited ( ..,  Delimiter :: Parenthesis ,  _) )  = { 
426+                                         iter. next ( ) ; 
427+                                         iter. peek ( ) 
428+                                     } 
429+                                 { 
430+                                     info. has_main_fn  = true ; 
431+                                     break ; 
443432                                } 
444-                             { 
445-                                 info. has_main_fn  = true ; 
446-                                 break ; 
447433                            } 
448434                        } 
449435                    } 
450-                     _ => { 
436+                     StmtKind :: Expr ( ref  expr)  => { 
437+                         if  matches ! ( expr. kind,  ast:: ExprKind :: Err ( _) )  { 
438+                             reset_error_count ( & psess) ; 
439+                             return  Err ( ( ) ) ; 
440+                         } 
451441                        has_non_items = true ; 
452442                    } 
443+                     StmtKind :: Let ( _)  | StmtKind :: Semi ( _)  | StmtKind :: Empty  => has_non_items = true , 
453444                } 
454445
455446                // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to 
0 commit comments