@@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItemKind};
5
5
use rustc_codegen_ssa:: traits:: CodegenBackend ;
6
6
use rustc_data_structures:: defer;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
+ use rustc_data_structures:: jobserver;
8
9
use rustc_data_structures:: stable_hasher:: StableHasher ;
9
10
use rustc_data_structures:: sync:: Lrc ;
10
11
use rustc_errors:: registry:: Registry ;
@@ -21,7 +22,7 @@ use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileN
21
22
use rustc_session:: filesearch:: { self , sysroot_candidates} ;
22
23
use rustc_session:: parse:: ParseSess ;
23
24
use rustc_session:: { lint, CompilerIO , EarlyDiagCtxt , Session } ;
24
- use rustc_span:: source_map:: FileLoader ;
25
+ use rustc_span:: source_map:: { FileLoader , RealFileLoader , SourceMapInputs } ;
25
26
use rustc_span:: symbol:: sym;
26
27
use rustc_span:: FileName ;
27
28
use std:: path:: PathBuf ;
@@ -323,6 +324,18 @@ pub struct Config {
323
324
pub expanded_args : Vec < String > ,
324
325
}
325
326
327
+ /// Initialize jobserver before getting `jobserver::client` and `build_session`.
328
+ pub ( crate ) fn initialize_checked_jobserver ( early_dcx : & EarlyDiagCtxt ) {
329
+ jobserver:: initialize_checked ( |err| {
330
+ #[ allow( rustc:: untranslatable_diagnostic) ]
331
+ #[ allow( rustc:: diagnostic_outside_of_impl) ]
332
+ early_dcx
333
+ . early_struct_warn ( err)
334
+ . with_note ( "the build environment is likely misconfigured" )
335
+ . emit ( )
336
+ } ) ;
337
+ }
338
+
326
339
// JUSTIFICATION: before session exists, only config
327
340
#[ allow( rustc:: bad_opt_access) ]
328
341
#[ allow( rustc:: untranslatable_diagnostic) ] // FIXME: make this translatable
@@ -334,20 +347,25 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
334
347
335
348
// Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
336
349
let early_dcx = EarlyDiagCtxt :: new ( config. opts . error_format ) ;
337
- early_dcx. initialize_checked_jobserver ( ) ;
350
+ initialize_checked_jobserver ( & early_dcx) ;
351
+
352
+ crate :: callbacks:: setup_callbacks ( ) ;
353
+
354
+ let sysroot = filesearch:: materialize_sysroot ( config. opts . maybe_sysroot . clone ( ) ) ;
355
+ let target = config:: build_target_config ( & early_dcx, & config. opts , & sysroot) ;
356
+ let file_loader = config. file_loader . unwrap_or_else ( || Box :: new ( RealFileLoader ) ) ;
357
+ let path_mapping = config. opts . file_path_mapping ( ) ;
358
+ let hash_kind = config. opts . unstable_opts . src_hash_algorithm ( & target) ;
338
359
339
360
util:: run_in_thread_pool_with_globals (
340
361
config. opts . edition ,
341
362
config. opts . unstable_opts . threads ,
363
+ SourceMapInputs { file_loader, path_mapping, hash_kind } ,
342
364
|current_gcx| {
343
- crate :: callbacks :: setup_callbacks ( ) ;
344
-
365
+ // The previous `early_dcx` can't be reused here because it doesn't
366
+ // impl `Send`. Creating a new one is fine.
345
367
let early_dcx = EarlyDiagCtxt :: new ( config. opts . error_format ) ;
346
368
347
- let sysroot = filesearch:: materialize_sysroot ( config. opts . maybe_sysroot . clone ( ) ) ;
348
-
349
- let target = config:: build_target_config ( & early_dcx, & config. opts , & sysroot) ;
350
-
351
369
let codegen_backend = match config. make_codegen_backend {
352
370
None => util:: get_codegen_backend (
353
371
& early_dcx,
@@ -372,9 +390,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
372
390
config. opts . unstable_opts . translate_directionality_markers ,
373
391
) {
374
392
Ok ( bundle) => bundle,
375
- Err ( e) => {
376
- early_dcx. early_fatal ( format ! ( "failed to load fluent bundle: {e}" ) ) ;
377
- }
393
+ Err ( e) => early_dcx. early_fatal ( format ! ( "failed to load fluent bundle: {e}" ) ) ,
378
394
} ;
379
395
380
396
let mut locale_resources = Vec :: from ( config. locale_resources ) ;
@@ -393,7 +409,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
393
409
config. registry . clone ( ) ,
394
410
locale_resources,
395
411
config. lint_caps ,
396
- config. file_loader ,
397
412
target,
398
413
sysroot,
399
414
util:: rustc_version_str ( ) . unwrap_or ( "unknown" ) ,
@@ -440,45 +455,43 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
440
455
current_gcx,
441
456
} ;
442
457
443
- rustc_span:: set_source_map ( compiler. sess . psess . clone_source_map ( ) , move || {
444
- // There are two paths out of `f`.
445
- // - Normal exit.
446
- // - Panic, e.g. triggered by `abort_if_errors`.
447
- //
448
- // We must run `finish_diagnostics` in both cases.
449
- let res = {
450
- // If `f` panics, `finish_diagnostics` will run during
451
- // unwinding because of the `defer`.
452
- let mut guar = None ;
453
- let sess_abort_guard = defer ( || {
454
- guar = compiler. sess . finish_diagnostics ( & config. registry ) ;
455
- } ) ;
456
-
457
- let res = f ( & compiler) ;
458
-
459
- // If `f` doesn't panic, `finish_diagnostics` will run
460
- // normally when `sess_abort_guard` is dropped.
461
- drop ( sess_abort_guard) ;
462
-
463
- // If `finish_diagnostics` emits errors (e.g. stashed
464
- // errors) we can't return an error directly, because the
465
- // return type of this function is `R`, not `Result<R, E>`.
466
- // But we need to communicate the errors' existence to the
467
- // caller, otherwise the caller might mistakenly think that
468
- // no errors occurred and return a zero exit code. So we
469
- // abort (panic) instead, similar to if `f` had panicked.
470
- if guar. is_some ( ) {
471
- compiler. sess . dcx ( ) . abort_if_errors ( ) ;
472
- }
458
+ // There are two paths out of `f`.
459
+ // - Normal exit.
460
+ // - Panic, e.g. triggered by `abort_if_errors`.
461
+ //
462
+ // We must run `finish_diagnostics` in both cases.
463
+ let res = {
464
+ // If `f` panics, `finish_diagnostics` will run during
465
+ // unwinding because of the `defer`.
466
+ let mut guar = None ;
467
+ let sess_abort_guard = defer ( || {
468
+ guar = compiler. sess . finish_diagnostics ( & config. registry ) ;
469
+ } ) ;
470
+
471
+ let res = f ( & compiler) ;
472
+
473
+ // If `f` doesn't panic, `finish_diagnostics` will run
474
+ // normally when `sess_abort_guard` is dropped.
475
+ drop ( sess_abort_guard) ;
476
+
477
+ // If `finish_diagnostics` emits errors (e.g. stashed
478
+ // errors) we can't return an error directly, because the
479
+ // return type of this function is `R`, not `Result<R, E>`.
480
+ // But we need to communicate the errors' existence to the
481
+ // caller, otherwise the caller might mistakenly think that
482
+ // no errors occurred and return a zero exit code. So we
483
+ // abort (panic) instead, similar to if `f` had panicked.
484
+ if guar. is_some ( ) {
485
+ compiler. sess . dcx ( ) . abort_if_errors ( ) ;
486
+ }
473
487
474
- res
475
- } ;
488
+ res
489
+ } ;
476
490
477
- let prof = compiler. sess . prof . clone ( ) ;
478
- prof. generic_activity ( "drop_compiler" ) . run ( move || drop ( compiler) ) ;
491
+ let prof = compiler. sess . prof . clone ( ) ;
492
+ prof. generic_activity ( "drop_compiler" ) . run ( move || drop ( compiler) ) ;
479
493
480
- res
481
- } )
494
+ res
482
495
} ,
483
496
)
484
497
}
0 commit comments