Skip to content

Commit f1807cc

Browse files
authored
Rollup merge of rust-lang#102769 - nnethercote:rustdoc-startup, r=jyn514
Clean up rustdoc startup Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help. Best reviewed one commit at a time. r? ```@jyn514```
2 parents 5c38950 + 1f0463a commit f1807cc

File tree

5 files changed

+109
-121
lines changed

5 files changed

+109
-121
lines changed

compiler/rustc_interface/src/interface.rs

+48-54
Original file line numberDiff line numberDiff line change
@@ -276,67 +276,61 @@ pub struct Config {
276276
pub registry: Registry,
277277
}
278278

279-
pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R) -> R {
280-
crate::callbacks::setup_callbacks();
281-
282-
let registry = &config.registry;
283-
let (mut sess, codegen_backend) = util::create_session(
284-
config.opts,
285-
config.crate_cfg,
286-
config.crate_check_cfg,
287-
config.diagnostic_output,
288-
config.file_loader,
289-
config.input_path.clone(),
290-
config.lint_caps,
291-
config.make_codegen_backend,
292-
registry.clone(),
293-
);
294-
295-
if let Some(parse_sess_created) = config.parse_sess_created {
296-
parse_sess_created(
297-
&mut Lrc::get_mut(&mut sess)
298-
.expect("create_session() should never share the returned session")
299-
.parse_sess,
300-
);
301-
}
302-
303-
let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
304-
305-
let compiler = Compiler {
306-
sess,
307-
codegen_backend,
308-
input: config.input,
309-
input_path: config.input_path,
310-
output_dir: config.output_dir,
311-
output_file: config.output_file,
312-
temps_dir,
313-
register_lints: config.register_lints,
314-
override_queries: config.override_queries,
315-
};
316-
317-
rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
318-
let r = {
319-
let _sess_abort_error = OnDrop(|| {
320-
compiler.sess.finish_diagnostics(registry);
321-
});
322-
323-
f(&compiler)
324-
};
325-
326-
let prof = compiler.sess.prof.clone();
327-
prof.generic_activity("drop_compiler").run(move || drop(compiler));
328-
r
329-
})
330-
}
331-
332279
// JUSTIFICATION: before session exists, only config
333280
#[allow(rustc::bad_opt_access)]
334281
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
335282
trace!("run_compiler");
336283
util::run_in_thread_pool_with_globals(
337284
config.opts.edition,
338285
config.opts.unstable_opts.threads,
339-
|| create_compiler_and_run(config, f),
286+
|| {
287+
crate::callbacks::setup_callbacks();
288+
289+
let registry = &config.registry;
290+
let (mut sess, codegen_backend) = util::create_session(
291+
config.opts,
292+
config.crate_cfg,
293+
config.crate_check_cfg,
294+
config.diagnostic_output,
295+
config.file_loader,
296+
config.input_path.clone(),
297+
config.lint_caps,
298+
config.make_codegen_backend,
299+
registry.clone(),
300+
);
301+
302+
if let Some(parse_sess_created) = config.parse_sess_created {
303+
parse_sess_created(&mut sess.parse_sess);
304+
}
305+
306+
let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
307+
308+
let compiler = Compiler {
309+
sess: Lrc::new(sess),
310+
codegen_backend: Lrc::new(codegen_backend),
311+
input: config.input,
312+
input_path: config.input_path,
313+
output_dir: config.output_dir,
314+
output_file: config.output_file,
315+
temps_dir,
316+
register_lints: config.register_lints,
317+
override_queries: config.override_queries,
318+
};
319+
320+
rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
321+
let r = {
322+
let _sess_abort_error = OnDrop(|| {
323+
compiler.sess.finish_diagnostics(registry);
324+
});
325+
326+
f(&compiler)
327+
};
328+
329+
let prof = compiler.sess.prof.clone();
330+
prof.generic_activity("drop_compiler").run(move || drop(compiler));
331+
r
332+
})
333+
},
340334
)
341335
}
342336

compiler/rustc_interface/src/util.rs

+21-24
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_codegen_ssa::traits::CodegenBackend;
55
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
66
#[cfg(parallel_compiler)]
77
use rustc_data_structures::jobserver;
8-
use rustc_data_structures::sync::Lrc;
98
use rustc_errors::registry::Registry;
109
#[cfg(parallel_compiler)]
1110
use rustc_middle::ty::tls;
@@ -73,7 +72,7 @@ pub fn create_session(
7372
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
7473
>,
7574
descriptions: Registry,
76-
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
75+
) -> (Session, Box<dyn CodegenBackend>) {
7776
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
7877
make_codegen_backend(&sopts)
7978
} else {
@@ -121,7 +120,7 @@ pub fn create_session(
121120
sess.parse_sess.config = cfg;
122121
sess.parse_sess.check_config = check_cfg;
123122

124-
(Lrc::new(sess), Lrc::new(codegen_backend))
123+
(sess, codegen_backend)
125124
}
126125

127126
const STACK_SIZE: usize = 8 * 1024 * 1024;
@@ -132,33 +131,31 @@ fn get_stack_size() -> Option<usize> {
132131
env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
133132
}
134133

135-
/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
136-
/// for `'static` bounds.
137134
#[cfg(not(parallel_compiler))]
138-
fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
139-
// SAFETY: join() is called immediately, so any closure captures are still
140-
// alive.
141-
match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
142-
Ok(v) => v,
143-
Err(e) => panic::resume_unwind(e),
144-
}
145-
}
146-
147-
#[cfg(not(parallel_compiler))]
148-
pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
135+
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
149136
edition: Edition,
150137
_threads: usize,
151138
f: F,
152139
) -> R {
153-
let mut cfg = thread::Builder::new().name("rustc".to_string());
154-
155-
if let Some(size) = get_stack_size() {
156-
cfg = cfg.stack_size(size);
157-
}
140+
// The thread pool is a single thread in the non-parallel compiler.
141+
thread::scope(|s| {
142+
let mut builder = thread::Builder::new().name("rustc".to_string());
143+
if let Some(size) = get_stack_size() {
144+
builder = builder.stack_size(size);
145+
}
158146

159-
let main_handler = move || rustc_span::create_session_globals_then(edition, f);
147+
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
148+
// name contains null bytes.
149+
let r = builder
150+
.spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f))
151+
.unwrap()
152+
.join();
160153

161-
scoped_thread(cfg, main_handler)
154+
match r {
155+
Ok(v) => v,
156+
Err(e) => panic::resume_unwind(e),
157+
}
158+
})
162159
}
163160

164161
/// Creates a new thread and forwards information in thread locals to it.
@@ -177,7 +174,7 @@ unsafe fn handle_deadlock() {
177174
}
178175

179176
#[cfg(parallel_compiler)]
180-
pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
177+
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
181178
edition: Edition,
182179
threads: usize,
183180
f: F,

src/librustdoc/doctest.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc_session::{lint, DiagnosticOutput, Session};
1818
use rustc_span::edition::Edition;
1919
use rustc_span::source_map::SourceMap;
2020
use rustc_span::symbol::sym;
21-
use rustc_span::Symbol;
2221
use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
2322
use rustc_target::spec::TargetTriple;
2423
use tempfile::Builder as TempFileBuilder;
@@ -125,7 +124,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
125124
let opts = scrape_test_config(crate_attrs);
126125
let enable_per_target_ignores = options.enable_per_target_ignores;
127126
let mut collector = Collector::new(
128-
tcx.crate_name(LOCAL_CRATE),
127+
tcx.crate_name(LOCAL_CRATE).to_string(),
129128
options,
130129
false,
131130
opts,
@@ -909,7 +908,7 @@ pub(crate) struct Collector {
909908
rustdoc_options: RustdocOptions,
910909
use_headers: bool,
911910
enable_per_target_ignores: bool,
912-
crate_name: Symbol,
911+
crate_name: String,
913912
opts: GlobalTestOptions,
914913
position: Span,
915914
source_map: Option<Lrc<SourceMap>>,
@@ -921,7 +920,7 @@ pub(crate) struct Collector {
921920

922921
impl Collector {
923922
pub(crate) fn new(
924-
crate_name: Symbol,
923+
crate_name: String,
925924
rustdoc_options: RustdocOptions,
926925
use_headers: bool,
927926
opts: GlobalTestOptions,
@@ -984,7 +983,7 @@ impl Tester for Collector {
984983
fn add_test(&mut self, test: String, config: LangString, line: usize) {
985984
let filename = self.get_filename();
986985
let name = self.generate_name(line, &filename);
987-
let crate_name = self.crate_name.to_string();
986+
let crate_name = self.crate_name.clone();
988987
let opts = self.opts.clone();
989988
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
990989
let rustdoc_options = self.rustdoc_options.clone();

src/librustdoc/lib.rs

+33-36
Original file line numberDiff line numberDiff line change
@@ -674,39 +674,6 @@ fn usage(argv0: &str) {
674674
/// A result type used by several functions under `main()`.
675675
type MainResult = Result<(), ErrorGuaranteed>;
676676

677-
fn main_args(at_args: &[String]) -> MainResult {
678-
let args = rustc_driver::args::arg_expand_all(at_args);
679-
680-
let mut options = getopts::Options::new();
681-
for option in opts() {
682-
(option.apply)(&mut options);
683-
}
684-
let matches = match options.parse(&args[1..]) {
685-
Ok(m) => m,
686-
Err(err) => {
687-
early_error(ErrorOutputType::default(), &err.to_string());
688-
}
689-
};
690-
691-
// Note that we discard any distinction between different non-zero exit
692-
// codes from `from_matches` here.
693-
let options = match config::Options::from_matches(&matches, args) {
694-
Ok(opts) => opts,
695-
Err(code) => {
696-
return if code == 0 {
697-
Ok(())
698-
} else {
699-
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
700-
};
701-
}
702-
};
703-
rustc_interface::util::run_in_thread_pool_with_globals(
704-
options.edition,
705-
1, // this runs single-threaded, even in a parallel compiler
706-
move || main_options(options),
707-
)
708-
}
709-
710677
fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
711678
match res {
712679
Ok(()) => Ok(()),
@@ -737,7 +704,33 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
737704
}
738705
}
739706

740-
fn main_options(options: config::Options) -> MainResult {
707+
fn main_args(at_args: &[String]) -> MainResult {
708+
let args = rustc_driver::args::arg_expand_all(at_args);
709+
710+
let mut options = getopts::Options::new();
711+
for option in opts() {
712+
(option.apply)(&mut options);
713+
}
714+
let matches = match options.parse(&args[1..]) {
715+
Ok(m) => m,
716+
Err(err) => {
717+
early_error(ErrorOutputType::default(), &err.to_string());
718+
}
719+
};
720+
721+
// Note that we discard any distinction between different non-zero exit
722+
// codes from `from_matches` here.
723+
let options = match config::Options::from_matches(&matches, args) {
724+
Ok(opts) => opts,
725+
Err(code) => {
726+
return if code == 0 {
727+
Ok(())
728+
} else {
729+
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
730+
};
731+
}
732+
};
733+
741734
let diag = core::new_handler(
742735
options.error_format,
743736
None,
@@ -749,9 +742,12 @@ fn main_options(options: config::Options) -> MainResult {
749742
(true, true) => return wrap_return(&diag, markdown::test(options)),
750743
(true, false) => return doctest::run(options),
751744
(false, true) => {
745+
// Session globals are required for symbol interning.
752746
return wrap_return(
753747
&diag,
754-
markdown::render(&options.input, options.render_options, options.edition),
748+
rustc_span::create_session_globals_then(options.edition, || {
749+
markdown::render(&options.input, options.render_options, options.edition)
750+
}),
755751
);
756752
}
757753
(false, false) => {}
@@ -777,9 +773,10 @@ fn main_options(options: config::Options) -> MainResult {
777773
let render_options = options.render_options.clone();
778774
let scrape_examples_options = options.scrape_examples_options.clone();
779775
let document_private = options.render_options.document_private;
776+
780777
let config = core::create_config(options);
781778

782-
interface::create_compiler_and_run(config, |compiler| {
779+
interface::run_compiler(config, |compiler| {
783780
let sess = compiler.session();
784781

785782
if sess.opts.describe_lints {

src/librustdoc/markdown.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::path::Path;
55

66
use rustc_span::edition::Edition;
77
use rustc_span::source_map::DUMMY_SP;
8-
use rustc_span::Symbol;
98

109
use crate::config::{Options, RenderOptions};
1110
use crate::doctest::{Collector, GlobalTestOptions};
@@ -36,6 +35,8 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
3635

3736
/// Render `input` (e.g., "foo.md") into an HTML file in `output`
3837
/// (e.g., output = "bar" => "bar/foo.html").
38+
///
39+
/// Requires session globals to be available, for symbol interning.
3940
pub(crate) fn render<P: AsRef<Path>>(
4041
input: P,
4142
options: RenderOptions,
@@ -133,7 +134,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
133134
let mut opts = GlobalTestOptions::default();
134135
opts.no_crate_inject = true;
135136
let mut collector = Collector::new(
136-
Symbol::intern(&options.input.display().to_string()),
137+
options.input.display().to_string(),
137138
options.clone(),
138139
true,
139140
opts,

0 commit comments

Comments
 (0)