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
|
@ -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)
|
||||
|
|
|
@ -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)>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue