Make SourceMap available for early debug-printing of Spans

Normally, we debug-print `Spans` using the `SourceMap` retrieved from
the global `TyCtxt`. However, we fall back to printing out the `Span`'s
raw fields (instead of a file and line number) when we try to print a
`Span` before a `TyCtxt` is available. This makes debugging early phases
of the compile, such as parsing, much more difficult.

This commit stores a `SourceMap` in `rustc_span::GlOBALS` as a fallback.
When a `TyCtxt` is not available, we try to retrieve one from `GLOBALS`
- only if this is not available do we fall back to the raw field output.

I'm not sure how to write a test for this - however, this can be
verified locally by setting `RUSTC_LOG="rustc_parse=debug"`, and
verifying that the output contains filenames and line numbers.
This commit is contained in:
Aaron Hill 2020-05-26 13:21:58 -04:00
parent 8c5402efdd
commit 717fd665ad
No known key found for this signature in database
GPG key ID: B4087E510E98B164
2 changed files with 51 additions and 14 deletions

View file

@ -186,17 +186,19 @@ pub fn run_compiler_in_existing_thread_pool<R>(
override_queries: config.override_queries, override_queries: config.override_queries,
}; };
let r = { rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
let _sess_abort_error = OnDrop(|| { let r = {
compiler.sess.finish_diagnostics(registry); let _sess_abort_error = OnDrop(|| {
}); compiler.sess.finish_diagnostics(registry);
});
f(&compiler) f(&compiler)
}; };
let prof = compiler.sess.prof.clone(); let prof = compiler.sess.prof.clone();
prof.generic_activity("drop_compiler").run(move || drop(compiler)); prof.generic_activity("drop_compiler").run(move || drop(compiler));
r r
})
} }
pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {

View file

@ -25,6 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
mod caching_source_map_view; mod caching_source_map_view;
pub mod source_map; pub mod source_map;
pub use self::caching_source_map_view::CachingSourceMapView; pub use self::caching_source_map_view::CachingSourceMapView;
use source_map::SourceMap;
pub mod edition; pub mod edition;
use edition::Edition; use edition::Edition;
@ -67,6 +68,7 @@ pub struct Globals {
symbol_interner: Lock<symbol::Interner>, symbol_interner: Lock<symbol::Interner>,
span_interner: Lock<span_encoding::SpanInterner>, span_interner: Lock<span_encoding::SpanInterner>,
hygiene_data: Lock<hygiene::HygieneData>, hygiene_data: Lock<hygiene::HygieneData>,
source_map: Lock<Option<Lrc<SourceMap>>>,
} }
impl Globals { impl Globals {
@ -75,6 +77,7 @@ impl Globals {
symbol_interner: Lock::new(symbol::Interner::fresh()), symbol_interner: Lock::new(symbol::Interner::fresh()),
span_interner: Lock::new(span_encoding::SpanInterner::default()), span_interner: Lock::new(span_encoding::SpanInterner::default()),
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
source_map: Lock::new(None),
} }
} }
} }
@ -641,12 +644,44 @@ impl rustc_serialize::UseSpecializedDecodable for Span {
} }
} }
/// Calls the provided closure, using the provided `SourceMap` to format
/// any spans that are debug-printed during the closure'e exectuino.
///
/// Normally, the global `TyCtxt` is used to retrieve the `SourceMap`
/// (see `rustc_interface::callbacks::span_debug1). However, some parts
/// of the compiler (e.g. `rustc_parse`) may debug-print `Span`s before
/// a `TyCtxt` is available. In this case, we fall back to
/// the `SourceMap` provided to this function. If that is not available,
/// we fall back to printing the raw `Span` field values
pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
GLOBALS.with(|globals| {
*globals.source_map.borrow_mut() = Some(source_map);
});
struct ClearSourceMap;
impl Drop for ClearSourceMap {
fn drop(&mut self) {
GLOBALS.with(|globals| {
globals.source_map.borrow_mut().take();
});
}
}
let _guard = ClearSourceMap;
f()
}
pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Span") GLOBALS.with(|globals| {
.field("lo", &span.lo()) if let Some(source_map) = &*globals.source_map.borrow() {
.field("hi", &span.hi()) write!(f, "{}", source_map.span_to_string(span))
.field("ctxt", &span.ctxt()) } else {
.finish() f.debug_struct("Span")
.field("lo", &span.lo())
.field("hi", &span.hi())
.field("ctxt", &span.ctxt())
.finish()
}
})
} }
impl fmt::Debug for Span { impl fmt::Debug for Span {