1
Fork 0

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:
Nicholas Nethercote 2024-03-21 14:17:00 +11:00
parent ff2e4ed1f1
commit 62c32aeeab
10 changed files with 118 additions and 116 deletions

View file

@ -49,7 +49,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
mod caching_source_map_view;
pub mod source_map;
pub use self::caching_source_map_view::CachingSourceMapView;
use source_map::SourceMap;
use source_map::{SourceMap, SourceMapInputs};
pub mod edition;
use edition::Edition;
@ -104,35 +104,35 @@ pub struct SessionGlobals {
metavar_spans: Lock<FxHashMap<Span, Span>>,
hygiene_data: Lock<hygiene::HygieneData>,
/// A reference to the source map in the `Session`. It's an `Option`
/// because it can't be initialized until `Session` is created, which
/// happens after `SessionGlobals`. `set_source_map` does the
/// initialization.
///
/// This field should only be used in places where the `Session` is truly
/// not available, such as `<Span as Debug>::fmt`.
source_map: Lock<Option<Lrc<SourceMap>>>,
/// The session's source map, if there is one. This field should only be
/// used in places where the `Session` is truly not available, such as
/// `<Span as Debug>::fmt`.
source_map: Option<Lrc<SourceMap>>,
}
impl SessionGlobals {
pub fn new(edition: Edition) -> SessionGlobals {
pub fn new(edition: Edition, sm_inputs: Option<SourceMapInputs>) -> SessionGlobals {
SessionGlobals {
symbol_interner: symbol::Interner::fresh(),
span_interner: Lock::new(span_encoding::SpanInterner::default()),
metavar_spans: Default::default(),
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
source_map: Lock::new(None),
source_map: sm_inputs.map(|inputs| Lrc::new(SourceMap::with_inputs(inputs))),
}
}
}
pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
pub fn create_session_globals_then<R>(
edition: Edition,
sm_inputs: Option<SourceMapInputs>,
f: impl FnOnce() -> R,
) -> R {
assert!(
!SESSION_GLOBALS.is_set(),
"SESSION_GLOBALS should never be overwritten! \
Use another thread if you need another SessionGlobals"
);
let session_globals = SessionGlobals::new(edition);
let session_globals = SessionGlobals::new(edition, sm_inputs);
SESSION_GLOBALS.set(&session_globals, f)
}
@ -145,12 +145,13 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
SESSION_GLOBALS.set(session_globals, f)
}
/// No source map.
pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
{
if !SESSION_GLOBALS.is_set() {
let session_globals = SessionGlobals::new(edition);
let session_globals = SessionGlobals::new(edition, None);
SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
} else {
SESSION_GLOBALS.with(f)
@ -164,8 +165,9 @@ where
SESSION_GLOBALS.with(f)
}
/// Default edition, no source map.
pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
create_session_globals_then(edition::DEFAULT_EDITION, f)
create_session_globals_then(edition::DEFAULT_EDITION, None, f)
}
// If this ever becomes non thread-local, `decode_syntax_context`
@ -1318,25 +1320,6 @@ impl<D: SpanDecoder> Decodable<D> for AttrId {
}
}
/// Insert `source_map` into the session globals for the duration of the
/// closure's execution.
pub fn set_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
with_session_globals(|session_globals| {
*session_globals.source_map.borrow_mut() = Some(source_map);
});
struct ClearSourceMap;
impl Drop for ClearSourceMap {
fn drop(&mut self) {
with_session_globals(|session_globals| {
session_globals.source_map.borrow_mut().take();
});
}
}
let _guard = ClearSourceMap;
f()
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Use the global `SourceMap` to print the span. If that's not
@ -1352,7 +1335,7 @@ impl fmt::Debug for Span {
if SESSION_GLOBALS.is_set() {
with_session_globals(|session_globals| {
if let Some(source_map) = &*session_globals.source_map.borrow() {
if let Some(source_map) = &session_globals.source_map {
write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
} else {
fallback(*self, f)

View file

@ -167,9 +167,17 @@ struct SourceMapFiles {
stable_id_to_source_file: UnhashMap<StableSourceFileId, Lrc<SourceFile>>,
}
/// Used to construct a `SourceMap` with `SourceMap::with_inputs`.
pub struct SourceMapInputs {
pub file_loader: Box<dyn FileLoader + Send + Sync>,
pub path_mapping: FilePathMapping,
pub hash_kind: SourceFileHashAlgorithm,
}
pub struct SourceMap {
files: RwLock<SourceMapFiles>,
file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
// This is used to apply the file path remapping as specified via
// `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
path_mapping: FilePathMapping,
@ -180,17 +188,15 @@ pub struct SourceMap {
impl SourceMap {
pub fn new(path_mapping: FilePathMapping) -> SourceMap {
Self::with_file_loader_and_hash_kind(
Box::new(RealFileLoader),
Self::with_inputs(SourceMapInputs {
file_loader: Box::new(RealFileLoader),
path_mapping,
SourceFileHashAlgorithm::Md5,
)
hash_kind: SourceFileHashAlgorithm::Md5,
})
}
pub fn with_file_loader_and_hash_kind(
file_loader: Box<dyn FileLoader + Sync + Send>,
path_mapping: FilePathMapping,
hash_kind: SourceFileHashAlgorithm,
pub fn with_inputs(
SourceMapInputs { file_loader, path_mapping, hash_kind }: SourceMapInputs,
) -> SourceMap {
SourceMap {
files: Default::default(),
@ -1054,6 +1060,10 @@ impl SourceMap {
}
}
pub fn get_source_map() -> Option<Lrc<SourceMap>> {
with_session_globals(|session_globals| session_globals.source_map.clone())
}
#[derive(Clone)]
pub struct FilePathMapping {
mapping: Vec<(PathBuf, PathBuf)>,