@@ -202,17 +202,7 @@ fn run_test(
202
202
opts : & TestOptions ,
203
203
edition : Edition ,
204
204
) -> Result < ( ) , TestFailure > {
205
- let ( test, line_offset) = match panic:: catch_unwind ( || {
206
- make_test ( test, Some ( cratename) , as_test_harness, opts, edition)
207
- } ) {
208
- Ok ( ( test, line_offset) ) => ( test, line_offset) ,
209
- Err ( cause) if cause. is :: < errors:: FatalErrorMarker > ( ) => {
210
- // If the parser used by `make_test` panicked due to a fatal error, pass the test code
211
- // through unchanged. The error will be reported during compilation.
212
- ( test. to_owned ( ) , 0 )
213
- }
214
- Err ( cause) => panic:: resume_unwind ( cause) ,
215
- } ;
205
+ let ( test, line_offset) = make_test ( test, Some ( cratename) , as_test_harness, opts, edition) ;
216
206
217
207
// FIXME(#44940): if doctests ever support path remapping, then this filename
218
208
// needs to be the result of `SourceMap::span_to_unmapped_path`.
@@ -362,11 +352,6 @@ fn run_test(
362
352
363
353
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
364
354
/// lines before the test code begins.
365
- ///
366
- /// # Panics
367
- ///
368
- /// This function uses the compiler's parser internally. The parser will panic if it encounters a
369
- /// fatal error while parsing the test.
370
355
pub fn make_test (
371
356
s : & str ,
372
357
cratename : Option < & str > ,
@@ -401,83 +386,94 @@ pub fn make_test(
401
386
402
387
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
403
388
// crate already is included.
404
- let ( already_has_main, already_has_extern_crate, found_macro) = with_globals ( edition, || {
405
- use errors:: emitter:: EmitterWriter ;
406
- use errors:: Handler ;
407
- use rustc_parse:: maybe_new_parser_from_source_str;
408
- use rustc_span:: source_map:: FilePathMapping ;
409
- use syntax:: sess:: ParseSess ;
410
-
411
- let filename = FileName :: anon_source_code ( s) ;
412
- let source = crates + & everything_else;
413
-
414
- // Any errors in parsing should also appear when the doctest is compiled for real, so just
415
- // send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
416
- let cm = Lrc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
417
- let emitter = EmitterWriter :: new ( box io:: sink ( ) , None , false , false , false , None , false ) ;
418
- // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
419
- let handler = Handler :: with_emitter ( false , None , box emitter) ;
420
- let sess = ParseSess :: with_span_handler ( handler, cm) ;
421
-
422
- let mut found_main = false ;
423
- let mut found_extern_crate = cratename. is_none ( ) ;
424
- let mut found_macro = false ;
425
-
426
- let mut parser = match maybe_new_parser_from_source_str ( & sess, filename, source) {
427
- Ok ( p) => p,
428
- Err ( errs) => {
429
- for mut err in errs {
430
- err. cancel ( ) ;
389
+ let result = rustc_driver:: catch_fatal_errors ( || {
390
+ with_globals ( edition, || {
391
+ use errors:: emitter:: EmitterWriter ;
392
+ use errors:: Handler ;
393
+ use rustc_parse:: maybe_new_parser_from_source_str;
394
+ use rustc_span:: source_map:: FilePathMapping ;
395
+ use syntax:: sess:: ParseSess ;
396
+
397
+ let filename = FileName :: anon_source_code ( s) ;
398
+ let source = crates + & everything_else;
399
+
400
+ // Any errors in parsing should also appear when the doctest is compiled for real, so just
401
+ // send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
402
+ let cm = Lrc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
403
+ let emitter =
404
+ EmitterWriter :: new ( box io:: sink ( ) , None , false , false , false , None , false ) ;
405
+ // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
406
+ let handler = Handler :: with_emitter ( false , None , box emitter) ;
407
+ let sess = ParseSess :: with_span_handler ( handler, cm) ;
408
+
409
+ let mut found_main = false ;
410
+ let mut found_extern_crate = cratename. is_none ( ) ;
411
+ let mut found_macro = false ;
412
+
413
+ let mut parser = match maybe_new_parser_from_source_str ( & sess, filename, source) {
414
+ Ok ( p) => p,
415
+ Err ( errs) => {
416
+ for mut err in errs {
417
+ err. cancel ( ) ;
418
+ }
419
+
420
+ return ( found_main, found_extern_crate, found_macro) ;
431
421
}
422
+ } ;
423
+
424
+ loop {
425
+ match parser. parse_item ( ) {
426
+ Ok ( Some ( item) ) => {
427
+ if !found_main {
428
+ if let ast:: ItemKind :: Fn ( ..) = item. kind {
429
+ if item. ident . name == sym:: main {
430
+ found_main = true ;
431
+ }
432
+ }
433
+ }
432
434
433
- return ( found_main, found_extern_crate, found_macro) ;
434
- }
435
- } ;
435
+ if !found_extern_crate {
436
+ if let ast:: ItemKind :: ExternCrate ( original) = item. kind {
437
+ // This code will never be reached if `cratename` is none because
438
+ // `found_extern_crate` is initialized to `true` if it is none.
439
+ let cratename = cratename. unwrap ( ) ;
436
440
437
- loop {
438
- match parser. parse_item ( ) {
439
- Ok ( Some ( item) ) => {
440
- if !found_main {
441
- if let ast:: ItemKind :: Fn ( ..) = item. kind {
442
- if item. ident . name == sym:: main {
443
- found_main = true ;
441
+ match original {
442
+ Some ( name) => found_extern_crate = name. as_str ( ) == cratename,
443
+ None => found_extern_crate = item. ident . as_str ( ) == cratename,
444
+ }
444
445
}
445
446
}
446
- }
447
-
448
- if !found_extern_crate {
449
- if let ast:: ItemKind :: ExternCrate ( original) = item. kind {
450
- // This code will never be reached if `cratename` is none because
451
- // `found_extern_crate` is initialized to `true` if it is none.
452
- let cratename = cratename. unwrap ( ) ;
453
447
454
- match original {
455
- Some ( name ) => found_extern_crate = name . as_str ( ) == cratename ,
456
- None => found_extern_crate = item . ident . as_str ( ) == cratename ,
448
+ if !found_macro {
449
+ if let ast :: ItemKind :: Mac ( .. ) = item . kind {
450
+ found_macro = true ;
457
451
}
458
452
}
459
- }
460
453
461
- if !found_macro {
462
- if let ast:: ItemKind :: Mac ( ..) = item. kind {
463
- found_macro = true ;
454
+ if found_main && found_extern_crate {
455
+ break ;
464
456
}
465
457
}
466
-
467
- if found_main && found_extern_crate {
458
+ Ok ( None ) => break ,
459
+ Err ( mut e) => {
460
+ e. cancel ( ) ;
468
461
break ;
469
462
}
470
463
}
471
- Ok ( None ) => break ,
472
- Err ( mut e) => {
473
- e. cancel ( ) ;
474
- break ;
475
- }
476
464
}
477
- }
478
465
479
- ( found_main, found_extern_crate, found_macro)
466
+ ( found_main, found_extern_crate, found_macro)
467
+ } )
480
468
} ) ;
469
+ let ( already_has_main, already_has_extern_crate, found_macro) = match result {
470
+ Ok ( result) => result,
471
+ Err ( ErrorReported ) => {
472
+ // If the parser panicked due to a fatal error, pass the test code through unchanged.
473
+ // The error will be reported during compilation.
474
+ return ( s. to_owned ( ) , 0 ) ;
475
+ }
476
+ } ;
481
477
482
478
// If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
483
479
// see it. In that case, run the old text-based scan to see if they at least have a main
0 commit comments