@@ -451,66 +451,72 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
451451}
452452
453453fn check_code ( cx : & LateContext < ' _ > , text : & str , span : Span ) {
454- fn has_needless_main ( code : & str ) -> bool {
455- let filename = FileName :: anon_source_code ( code) ;
456-
457- let sm = Lrc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
458- let emitter = EmitterWriter :: new ( box io:: sink ( ) , None , false , false , false , None , false ) ;
459- let handler = Handler :: with_emitter ( false , None , box emitter) ;
460- let sess = ParseSess :: with_span_handler ( handler, sm) ;
461-
462- let mut parser = match maybe_new_parser_from_source_str ( & sess, filename, code. into ( ) ) {
463- Ok ( p) => p,
464- Err ( errs) => {
465- for mut err in errs {
466- err. cancel ( ) ;
467- }
468- return false ;
469- } ,
470- } ;
471-
472- let mut relevant_main_found = false ;
473- loop {
474- match parser. parse_item ( ) {
475- Ok ( Some ( item) ) => match & item. kind {
476- // Tests with one of these items are ignored
477- ItemKind :: Static ( ..)
478- | ItemKind :: Const ( ..)
479- | ItemKind :: ExternCrate ( ..)
480- | ItemKind :: ForeignMod ( ..) => return false ,
481- // We found a main function ...
482- ItemKind :: Fn ( _, sig, _, Some ( block) ) if item. ident . name == sym:: main => {
483- let is_async = matches ! ( sig. header. asyncness, Async :: Yes { .. } ) ;
484- let returns_nothing = match & sig. decl . output {
485- FnRetTy :: Default ( ..) => true ,
486- FnRetTy :: Ty ( ty) if ty. kind . is_unit ( ) => true ,
487- _ => false ,
488- } ;
489-
490- if returns_nothing && !is_async && !block. stmts . is_empty ( ) {
491- // This main function should be linted, but only if there are no other functions
492- relevant_main_found = true ;
493- } else {
494- // This main function should not be linted, we're done
495- return false ;
454+ fn has_needless_main ( cx : & LateContext < ' _ > , code : & str ) -> bool {
455+ rustc_driver:: catch_fatal_errors ( || {
456+ rustc_span:: with_session_globals ( cx. tcx . sess . edition ( ) , || {
457+ let filename = FileName :: anon_source_code ( code) ;
458+
459+ let sm = Lrc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
460+ let emitter = EmitterWriter :: new ( box io:: sink ( ) , None , false , false , false , None , false ) ;
461+ let handler = Handler :: with_emitter ( false , None , box emitter) ;
462+ let sess = ParseSess :: with_span_handler ( handler, sm) ;
463+
464+ let mut parser = match maybe_new_parser_from_source_str ( & sess, filename, code. into ( ) ) {
465+ Ok ( p) => p,
466+ Err ( errs) => {
467+ for mut err in errs {
468+ err. cancel ( ) ;
496469 }
470+ return false ;
497471 } ,
498- // Another function was found; this case is ignored too
499- ItemKind :: Fn ( ..) => return false ,
500- _ => { } ,
501- } ,
502- Ok ( None ) => break ,
503- Err ( mut e) => {
504- e. cancel ( ) ;
505- return false ;
506- } ,
507- }
508- }
472+ } ;
473+
474+ let mut relevant_main_found = false ;
475+ loop {
476+ match parser. parse_item ( ) {
477+ Ok ( Some ( item) ) => match & item. kind {
478+ // Tests with one of these items are ignored
479+ ItemKind :: Static ( ..)
480+ | ItemKind :: Const ( ..)
481+ | ItemKind :: ExternCrate ( ..)
482+ | ItemKind :: ForeignMod ( ..) => return false ,
483+ // We found a main function ...
484+ ItemKind :: Fn ( _, sig, _, Some ( block) ) if item. ident . name == sym:: main => {
485+ let is_async = matches ! ( sig. header. asyncness, Async :: Yes { .. } ) ;
486+ let returns_nothing = match & sig. decl . output {
487+ FnRetTy :: Default ( ..) => true ,
488+ FnRetTy :: Ty ( ty) if ty. kind . is_unit ( ) => true ,
489+ _ => false ,
490+ } ;
491+
492+ if returns_nothing && !is_async && !block. stmts . is_empty ( ) {
493+ // This main function should be linted, but only if there are no other functions
494+ relevant_main_found = true ;
495+ } else {
496+ // This main function should not be linted, we're done
497+ return false ;
498+ }
499+ } ,
500+ // Another function was found; this case is ignored too
501+ ItemKind :: Fn ( ..) => return false ,
502+ _ => { } ,
503+ } ,
504+ Ok ( None ) => break ,
505+ Err ( mut e) => {
506+ e. cancel ( ) ;
507+ return false ;
508+ } ,
509+ }
510+ }
509511
510- relevant_main_found
512+ relevant_main_found
513+ } )
514+ } )
515+ . ok ( )
516+ . unwrap_or_default ( )
511517 }
512518
513- if has_needless_main ( text) {
519+ if has_needless_main ( cx , text) {
514520 span_lint ( cx, NEEDLESS_DOCTEST_MAIN , span, "needless `fn main` in doctest" ) ;
515521 }
516522}
0 commit comments