diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 74b8e88a97790..571923b546293 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - create_session_globals_then(Edition::Edition2024, || { + create_session_globals_then(Edition::Edition2024, None, || { let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], ""); let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], ""); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index da2fb490a36f2..c5b81dbd67919 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItemKind}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::defer; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::jobserver; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; @@ -21,7 +22,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; @@ -323,6 +324,18 @@ pub struct Config { pub expanded_args: Vec, } +/// Initialize jobserver before getting `jobserver::client` and `build_session`. +pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) { + jobserver::initialize_checked(|err| { + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + early_dcx + .early_struct_warn(err) + .with_note("the build environment is likely misconfigured") + .emit() + }); +} + // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable @@ -334,20 +347,25 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); - early_dcx.initialize_checked_jobserver(); + initialize_checked_jobserver(&early_dcx); + + 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 +390,7 @@ pub fn run_compiler(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 +409,6 @@ pub fn run_compiler(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 +455,43 @@ pub fn run_compiler(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); - }); - - 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 `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`. - // 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(); - } + // 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); + + // 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`. + // 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 - }; + res + }; - let prof = compiler.sess.prof.clone(); - prof.generic_activity("drop_compiler").run(move || drop(compiler)); + let prof = compiler.sess.prof.clone(); + prof.generic_activity("drop_compiler").run(move || drop(compiler)); - res - }) + res }, ) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 923581d1cb696..e563728c893d6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -1,5 +1,5 @@ #![allow(rustc::bad_opt_access)] -use crate::interface::parse_cfg; +use crate::interface::{initialize_checked_jobserver, parse_cfg}; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ @@ -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}; @@ -25,42 +26,52 @@ use std::num::NonZero; use std::path::{Path, PathBuf}; use std::sync::Arc; -fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { +fn sess_and_cfg(args: &[&'static str], f: F) +where + F: FnOnce(Session, Cfg), +{ let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); - early_dcx.initialize_checked_jobserver(); + initialize_checked_jobserver(&early_dcx); - let registry = registry::Registry::new(&[]); + let matches = optgroups().parse(args).unwrap(); let sessopts = build_session_options(&mut early_dcx, &matches); - 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() }, - output_dir: None, - output_file: None, - temps_dir, - }; - 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, + }); - let sess = build_session( - early_dcx, - sessopts, - io, - None, - registry, - vec![], - Default::default(), - None, - target, - sysroot, - "", - None, - Arc::default(), - Default::default(), - ); - let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg")); - (sess, cfg) + 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() }, + output_dir: None, + output_file: None, + temps_dir, + }; + + let sess = build_session( + early_dcx, + sessopts, + io, + None, + registry::Registry::new(&[]), + vec![], + Default::default(), + target, + sysroot, + "", + None, + Arc::default(), + Default::default(), + ); + let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg")); + let cfg = build_configuration(&sess, cfg); + f(sess, cfg) + }); } fn new_public_extern_entry(locations: I) -> ExternEntry @@ -125,21 +136,15 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) { // When the user supplies --test we should implicitly supply --cfg test #[test] fn test_switch_implies_cfg_test() { - rustc_span::create_default_session_globals_then(|| { - let matches = optgroups().parse(&["--test".to_string()]).unwrap(); - let (sess, cfg) = mk_session(matches); - let cfg = build_configuration(&sess, cfg); + sess_and_cfg(&["--test"], |_sess, cfg| { assert!(cfg.contains(&(sym::test, None))); - }); + }) } // When the user supplies --test and --cfg test, don't implicitly add another --cfg test #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { - rustc_span::create_default_session_globals_then(|| { - let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); - let (sess, cfg) = mk_session(matches); - let cfg = build_configuration(&sess, cfg); + sess_and_cfg(&["--test", "--cfg=test"], |_sess, cfg| { let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); assert!(test_items.next().is_none()); @@ -148,22 +153,15 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { #[test] fn test_can_print_warnings() { - rustc_span::create_default_session_globals_then(|| { - let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + sess_and_cfg(&["-Awarnings"], |sess, _cfg| { assert!(!sess.dcx().can_emit_warnings()); }); - rustc_span::create_default_session_globals_then(|| { - let matches = - optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + sess_and_cfg(&["-Awarnings", "-Dwarnings"], |sess, _cfg| { assert!(sess.dcx().can_emit_warnings()); }); - rustc_span::create_default_session_globals_then(|| { - let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + sess_and_cfg(&["-Adead_code"], |sess, _cfg| { assert!(sess.dcx().can_emit_warnings()); }); } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d0f04fccc4810..02dcfe9c8dffb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -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 R + Send, R: Send>( +fn run_in_thread_with_globals 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 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 R + Send, R: S pub(crate) fn run_in_thread_pool_with_globals 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 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 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 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 diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e4b67cde244fb..81257f9be8823 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -17,7 +17,7 @@ //! rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap(); //! //! let edition = rustc_span::edition::Edition::Edition2021; -//! rustc_span::create_session_globals_then(edition, || { +//! rustc_span::create_session_globals_then(edition, None, || { //! /* ... */ //! }); //! } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d9fc43625ef5f..2a7b5650fc214 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1125,7 +1125,7 @@ impl Options { || self.unstable_opts.query_dep_graph } - pub(crate) fn file_path_mapping(&self) -> FilePathMapping { + pub fn file_path_mapping(&self) -> FilePathMapping { file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts) } @@ -1162,6 +1162,16 @@ impl UnstableOptions { track_diagnostics: self.track_diagnostics, } } + + pub fn src_hash_algorithm(&self, target: &Target) -> SourceFileHashAlgorithm { + self.src_hash_algorithm.unwrap_or_else(|| { + if target.is_like_msvc { + SourceFileHashAlgorithm::Sha256 + } else { + SourceFileHashAlgorithm::Md5 + } + }) + } } // The type of entry function, so users can have their own entry functions diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 38642efadbd80..b63c119eee0e4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -28,9 +28,9 @@ use rustc_errors::{ use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, FilePathMapping, RealFileLoader, SourceMap}; +use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{FileNameDisplayPreference, RealFileName}; -use rustc_span::{SourceFileHashAlgorithm, Span, Symbol}; +use rustc_span::{Span, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; use rustc_target::spec::{ @@ -988,7 +988,6 @@ pub fn build_session( registry: rustc_errors::registry::Registry, fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap, - file_loader: Option>, target: Target, sysroot: PathBuf, cfg_version: &'static str, @@ -1015,24 +1014,11 @@ pub fn build_session( early_dcx.early_warn(warning) } - let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); - let hash_kind = sopts.unstable_opts.src_hash_algorithm.unwrap_or_else(|| { - if target.is_like_msvc { - SourceFileHashAlgorithm::Sha256 - } else { - SourceFileHashAlgorithm::Md5 - } - }); - let source_map = Lrc::new(SourceMap::with_file_loader_and_hash_kind( - loader, - sopts.file_path_mapping(), - hash_kind, - )); - let fallback_bundle = fallback_fluent_bundle( fluent_resources, sopts.unstable_opts.translate_directionality_markers, ); + let source_map = rustc_span::source_map::get_source_map().unwrap(); let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle); let mut dcx = @@ -1411,16 +1397,10 @@ impl EarlyDiagCtxt { self.dcx.warn(msg) } - pub fn initialize_checked_jobserver(&self) { - // initialize jobserver before getting `jobserver::client` and `build_session`. - jobserver::initialize_checked(|err| { - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - self.dcx - .struct_warn(err) - .with_note("the build environment is likely misconfigured") - .emit() - }); + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub fn early_struct_warn(&self, msg: impl Into) -> Diag<'_, ()> { + self.dcx.struct_warn(msg) } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c1e1175b4bd6b..f749d4eb83368 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -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>, hygiene_data: Lock, - /// 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 `::fmt`. - source_map: Lock>>, + /// 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 + /// `::fmt`. + source_map: Option>, } impl SessionGlobals { - pub fn new(edition: Edition) -> SessionGlobals { + pub fn new(edition: Edition, sm_inputs: Option) -> 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(edition: Edition, f: impl FnOnce() -> R) -> R { +pub fn create_session_globals_then( + edition: Edition, + sm_inputs: Option, + 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(session_globals: &SessionGlobals, f: impl FnO SESSION_GLOBALS.set(session_globals, f) } +/// No source map. pub fn create_session_if_not_set_then(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(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 Decodable for AttrId { } } -/// Insert `source_map` into the session globals for the duration of the -/// closure's execution. -pub fn set_source_map T>(source_map: Lrc, 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) diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 93d5f06a16736..e3e76caebaf00 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -167,9 +167,17 @@ struct SourceMapFiles { stable_id_to_source_file: UnhashMap>, } +/// Used to construct a `SourceMap` with `SourceMap::with_inputs`. +pub struct SourceMapInputs { + pub file_loader: Box, + pub path_mapping: FilePathMapping, + pub hash_kind: SourceFileHashAlgorithm, +} + pub struct SourceMap { files: RwLock, file_loader: IntoDynSyncSend>, + // 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, - 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> { + with_session_globals(|session_globals| session_globals.source_map.clone()) +} + #[derive(Clone)] pub struct FilePathMapping { mapping: Vec<(PathBuf, PathBuf)>, diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index e55a988321b34..651f2ebaee6f4 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -38,7 +38,7 @@ pub fn check( // of all `#[test]` attributes in not ignored code examples fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec>) { rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, || { + rustc_span::create_session_globals_then(edition, None, || { let mut test_attr_spans = vec![]; let filename = FileName::anon_source_code(&code);