Construct SourceMap
at the same time as SessionGlobals
.
Currently `SourceMap` is constructed slightly later than `SessionGlobals`, and inserted. This commit changes things so they are done at the same time. Benefits: - `SessionGlobals::source_map` changes from `Lock<Option<Lrc<SourceMap>>>` to `Option<Lrc<SourceMap>>`. It's still optional, but mutability isn't required because it's initialized at construction. - `set_source_map` is removed, simplifying `run_compiler`, which is good because that's a critical function and it's nice to make it simpler. This requires moving things around a bit, so the necessary inputs are available when `SessionGlobals` is created, in particular the `loader` and `hash_kind`, which are no longer computed by `build_session`. These inputs are captured by the new `SourceMapInputs` type, which is threaded through various places.
This commit is contained in:
parent
ff2e4ed1f1
commit
62c32aeeab
10 changed files with 118 additions and 116 deletions
|
@ -21,7 +21,7 @@ use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileN
|
|||
use rustc_session::filesearch::{self, sysroot_candidates};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
|
||||
use rustc_span::source_map::FileLoader;
|
||||
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::FileName;
|
||||
use std::path::PathBuf;
|
||||
|
@ -336,18 +336,23 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
|
||||
early_dcx.initialize_checked_jobserver();
|
||||
|
||||
crate::callbacks::setup_callbacks();
|
||||
|
||||
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
|
||||
let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
|
||||
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
|
||||
let path_mapping = config.opts.file_path_mapping();
|
||||
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
|
||||
|
||||
util::run_in_thread_pool_with_globals(
|
||||
config.opts.edition,
|
||||
config.opts.unstable_opts.threads,
|
||||
SourceMapInputs { file_loader, path_mapping, hash_kind },
|
||||
|current_gcx| {
|
||||
crate::callbacks::setup_callbacks();
|
||||
|
||||
// The previous `early_dcx` can't be reused here because it doesn't
|
||||
// impl `Send`. Creating a new one is fine.
|
||||
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
|
||||
|
||||
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
|
||||
|
||||
let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
|
||||
|
||||
let codegen_backend = match config.make_codegen_backend {
|
||||
None => util::get_codegen_backend(
|
||||
&early_dcx,
|
||||
|
@ -372,9 +377,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
config.opts.unstable_opts.translate_directionality_markers,
|
||||
) {
|
||||
Ok(bundle) => bundle,
|
||||
Err(e) => {
|
||||
early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"));
|
||||
}
|
||||
Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
|
||||
};
|
||||
|
||||
let mut locale_resources = Vec::from(config.locale_resources);
|
||||
|
@ -393,7 +396,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
config.registry.clone(),
|
||||
locale_resources,
|
||||
config.lint_caps,
|
||||
config.file_loader,
|
||||
target,
|
||||
sysroot,
|
||||
util::rustc_version_str().unwrap_or("unknown"),
|
||||
|
@ -440,45 +442,43 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
current_gcx,
|
||||
};
|
||||
|
||||
rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
|
||||
// There are two paths out of `f`.
|
||||
// - Normal exit.
|
||||
// - Panic, e.g. triggered by `abort_if_errors`.
|
||||
//
|
||||
// We must run `finish_diagnostics` in both cases.
|
||||
let res = {
|
||||
// If `f` panics, `finish_diagnostics` will run during
|
||||
// unwinding because of the `defer`.
|
||||
let mut guar = None;
|
||||
let sess_abort_guard = defer(|| {
|
||||
guar = compiler.sess.finish_diagnostics(&config.registry);
|
||||
});
|
||||
// There are two paths out of `f`.
|
||||
// - Normal exit.
|
||||
// - Panic, e.g. triggered by `abort_if_errors`.
|
||||
//
|
||||
// We must run `finish_diagnostics` in both cases.
|
||||
let res = {
|
||||
// If `f` panics, `finish_diagnostics` will run during
|
||||
// unwinding because of the `defer`.
|
||||
let mut guar = None;
|
||||
let sess_abort_guard = defer(|| {
|
||||
guar = compiler.sess.finish_diagnostics(&config.registry);
|
||||
});
|
||||
|
||||
let res = f(&compiler);
|
||||
let res = f(&compiler);
|
||||
|
||||
// If `f` doesn't panic, `finish_diagnostics` will run
|
||||
// normally when `sess_abort_guard` is dropped.
|
||||
drop(sess_abort_guard);
|
||||
// If `f` doesn't panic, `finish_diagnostics` will run
|
||||
// normally when `sess_abort_guard` is dropped.
|
||||
drop(sess_abort_guard);
|
||||
|
||||
// If `finish_diagnostics` emits errors (e.g. stashed
|
||||
// errors) we can't return an error directly, because the
|
||||
// return type of this function is `R`, not `Result<R, E>`.
|
||||
// But we need to communicate the errors' existence to the
|
||||
// caller, otherwise the caller might mistakenly think that
|
||||
// no errors occurred and return a zero exit code. So we
|
||||
// abort (panic) instead, similar to if `f` had panicked.
|
||||
if guar.is_some() {
|
||||
compiler.sess.dcx().abort_if_errors();
|
||||
}
|
||||
|
||||
res
|
||||
};
|
||||
|
||||
let prof = compiler.sess.prof.clone();
|
||||
prof.generic_activity("drop_compiler").run(move || drop(compiler));
|
||||
// If `finish_diagnostics` emits errors (e.g. stashed
|
||||
// errors) we can't return an error directly, because the
|
||||
// return type of this function is `R`, not `Result<R, E>`.
|
||||
// But we need to communicate the errors' existence to the
|
||||
// caller, otherwise the caller might mistakenly think that
|
||||
// no errors occurred and return a zero exit code. So we
|
||||
// abort (panic) instead, similar to if `f` had panicked.
|
||||
if guar.is_some() {
|
||||
compiler.sess.dcx().abort_if_errors();
|
||||
}
|
||||
|
||||
res
|
||||
})
|
||||
};
|
||||
|
||||
let prof = compiler.sess.prof.clone();
|
||||
prof.generic_activity("drop_compiler").run(move || drop(compiler));
|
||||
|
||||
res
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use rustc_session::search_paths::SearchPath;
|
|||
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
||||
use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session};
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION};
|
||||
use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{FileName, SourceFileHashAlgorithm};
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
|
||||
|
@ -36,8 +37,14 @@ where
|
|||
let sessopts = build_session_options(&mut early_dcx, &matches);
|
||||
let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
|
||||
let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot);
|
||||
let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
|
||||
let sm_inputs = Some(SourceMapInputs {
|
||||
file_loader: Box::new(RealFileLoader) as _,
|
||||
path_mapping: sessopts.file_path_mapping(),
|
||||
hash_kind,
|
||||
});
|
||||
|
||||
rustc_span::create_default_session_globals_then(|| {
|
||||
rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || {
|
||||
let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
|
||||
let io = CompilerIO {
|
||||
input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
|
||||
|
@ -45,6 +52,7 @@ where
|
|||
output_file: None,
|
||||
temps_dir,
|
||||
};
|
||||
|
||||
let sess = build_session(
|
||||
early_dcx,
|
||||
sessopts,
|
||||
|
@ -53,7 +61,6 @@ where
|
|||
registry::Registry::new(&[]),
|
||||
vec![],
|
||||
Default::default(),
|
||||
None,
|
||||
target,
|
||||
sysroot,
|
||||
"",
|
||||
|
|
|
@ -14,6 +14,7 @@ use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
|
|||
use rustc_session::{filesearch, Session};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::SourceMapInputs;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_target::spec::Target;
|
||||
use session::output::{categorize_crate_type, CRATE_TYPES};
|
||||
|
@ -65,8 +66,9 @@ fn init_stack_size() -> usize {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
|
||||
fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
|
||||
edition: Edition,
|
||||
sm_inputs: SourceMapInputs,
|
||||
f: F,
|
||||
) -> R {
|
||||
// The "thread pool" is a single spawned thread in the non-parallel
|
||||
|
@ -84,7 +86,9 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
|
|||
// name contains null bytes.
|
||||
let r = builder
|
||||
.spawn_scoped(s, move || {
|
||||
rustc_span::create_session_globals_then(edition, || f(CurrentGcx::new()))
|
||||
rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
|
||||
f(CurrentGcx::new())
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
.join();
|
||||
|
@ -100,15 +104,17 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
|
|||
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
|
||||
edition: Edition,
|
||||
_threads: usize,
|
||||
sm_inputs: SourceMapInputs,
|
||||
f: F,
|
||||
) -> R {
|
||||
run_in_thread_with_globals(edition, f)
|
||||
run_in_thread_with_globals(edition, sm_inputs, f)
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
|
||||
edition: Edition,
|
||||
threads: usize,
|
||||
sm_inputs: SourceMapInputs,
|
||||
f: F,
|
||||
) -> R {
|
||||
use rustc_data_structures::{defer, jobserver, sync::FromDyn};
|
||||
|
@ -120,7 +126,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
|
|||
let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
|
||||
|
||||
if !sync::is_dyn_thread_safe() {
|
||||
return run_in_thread_with_globals(edition, |current_gcx| {
|
||||
return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| {
|
||||
// Register the thread for use with the `WorkerLocal` type.
|
||||
registry.register();
|
||||
|
||||
|
@ -169,7 +175,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
|
|||
// pool. Upon creation, each worker thread created gets a copy of the
|
||||
// session globals in TLS. This is possible because `SessionGlobals` impls
|
||||
// `Send` in the parallel compiler.
|
||||
rustc_span::create_session_globals_then(edition, || {
|
||||
rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
|
||||
rustc_span::with_session_globals(|session_globals| {
|
||||
let session_globals = FromDyn::from(session_globals);
|
||||
builder
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue