Skip to content

Commit af1ca15

Browse files
authored
Rollup merge of #132410 - bjorn3:yet_another_driver_refactor_round, r=cjgillot
Some more refactorings towards removing driver queries Follow up to #127184 ## Custom driver breaking change The `after_analysis` callback is changed to accept `TyCtxt` instead of `Queries`. The only safe query in `Queries` to call at this point is `global_ctxt()` which allows you to enter the `TyCtxt` either way. To fix your custom driver, replace the `queries: &'tcx Queries<'tcx>` argument with `tcx: TyCtxt<'tcx>` and remove your `queries.global_ctxt().unwrap().enter(|tcx| { ... })` call and only keep the contents of the closure. ## Custom driver deprecation The `after_crate_root_parsing` callback is now deprecated. Several custom drivers are incorrectly calling `queries.global_ctxt()` from inside of it, which causes some driver code to be skipped. As such I would like to either remove it in the future or if custom drivers still need it, change it to accept an `&rustc_ast::Crate` instead.
2 parents 6b6a867 + dc65c63 commit af1ca15

33 files changed

+227
-195
lines changed

Diff for: compiler/rustc_driver_impl/src/lib.rs

+51-57
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ pub trait Callbacks {
160160
/// Called after parsing the crate root. Submodules are not yet parsed when
161161
/// this callback is called. Return value instructs the compiler whether to
162162
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
163+
#[deprecated = "This callback will likely be removed or stop giving access \
164+
to the TyCtxt in the future. Use either the after_expansion \
165+
or the after_analysis callback instead."]
163166
fn after_crate_root_parsing<'tcx>(
164167
&mut self,
165168
_compiler: &interface::Compiler,
@@ -181,7 +184,7 @@ pub trait Callbacks {
181184
fn after_analysis<'tcx>(
182185
&mut self,
183186
_compiler: &interface::Compiler,
184-
_queries: &'tcx Queries<'tcx>,
187+
_tcx: TyCtxt<'tcx>,
185188
) -> Compilation {
186189
Compilation::Continue
187190
}
@@ -335,19 +338,12 @@ fn run_compiler(
335338
expanded_args: args,
336339
};
337340

338-
let has_input = match make_input(&default_early_dcx, &matches.free) {
339-
Err(reported) => return Err(reported),
340-
Ok(Some(input)) => {
341+
let has_input = match make_input(&default_early_dcx, &matches.free)? {
342+
Some(input) => {
341343
config.input = input;
342344
true // has input: normal compilation
343345
}
344-
Ok(None) => match matches.free.as_slice() {
345-
[] => false, // no input: we will exit early
346-
[_] => panic!("make_input should have provided valid inputs"),
347-
[fst, snd, ..] => default_early_dcx.early_fatal(format!(
348-
"multiple input filenames provided (first two filenames are `{fst}` and `{snd}`)"
349-
)),
350-
},
346+
None => false, // no input: we will exit early
351347
};
352348

353349
drop(default_early_dcx);
@@ -405,10 +401,6 @@ fn run_compiler(
405401
queries.global_ctxt()?.enter(|tcx| {
406402
tcx.ensure().early_lint_checks(());
407403
pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx });
408-
Ok(())
409-
})?;
410-
411-
queries.global_ctxt()?.enter(|tcx| {
412404
passes::write_dep_info(tcx);
413405
});
414406
} else {
@@ -421,6 +413,7 @@ fn run_compiler(
421413
return early_exit();
422414
}
423415

416+
#[allow(deprecated)]
424417
if callbacks.after_crate_root_parsing(compiler, queries) == Compilation::Stop {
425418
return early_exit();
426419
}
@@ -442,25 +435,23 @@ fn run_compiler(
442435

443436
queries.global_ctxt()?.enter(|tcx| {
444437
passes::write_dep_info(tcx);
445-
});
446438

447-
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
448-
&& sess.opts.output_types.len() == 1
449-
{
450-
return early_exit();
451-
}
439+
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
440+
&& sess.opts.output_types.len() == 1
441+
{
442+
return early_exit();
443+
}
452444

453-
if sess.opts.unstable_opts.no_analysis {
454-
return early_exit();
455-
}
445+
if sess.opts.unstable_opts.no_analysis {
446+
return early_exit();
447+
}
456448

457-
queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?;
449+
tcx.analysis(())?;
458450

459-
if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
460-
return early_exit();
461-
}
451+
if callbacks.after_analysis(compiler, tcx) == Compilation::Stop {
452+
return early_exit();
453+
}
462454

463-
queries.global_ctxt()?.enter(|tcx| {
464455
Ok(Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)?))
465456
})
466457
})?;
@@ -509,37 +500,40 @@ fn make_input(
509500
early_dcx: &EarlyDiagCtxt,
510501
free_matches: &[String],
511502
) -> Result<Option<Input>, ErrorGuaranteed> {
512-
let [input_file] = free_matches else { return Ok(None) };
513-
514-
if input_file != "-" {
515-
// Normal `Input::File`
516-
return Ok(Some(Input::File(PathBuf::from(input_file))));
517-
}
518-
519-
// read from stdin as `Input::Str`
520-
let mut input = String::new();
521-
if io::stdin().read_to_string(&mut input).is_err() {
522-
// Immediately stop compilation if there was an issue reading
523-
// the input (for example if the input stream is not UTF-8).
524-
let reported =
525-
early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
526-
return Err(reported);
527-
}
503+
match free_matches {
504+
[] => Ok(None), // no input: we will exit early,
505+
[ifile] if ifile == "-" => {
506+
// read from stdin as `Input::Str`
507+
let mut input = String::new();
508+
if io::stdin().read_to_string(&mut input).is_err() {
509+
// Immediately stop compilation if there was an issue reading
510+
// the input (for example if the input stream is not UTF-8).
511+
let reported = early_dcx
512+
.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
513+
return Err(reported);
514+
}
528515

529-
let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
530-
Ok(path) => {
531-
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
532-
"when UNSTABLE_RUSTDOC_TEST_PATH is set \
516+
let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
517+
Ok(path) => {
518+
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
519+
"when UNSTABLE_RUSTDOC_TEST_PATH is set \
533520
UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
534-
);
535-
let line = isize::from_str_radix(&line, 10)
536-
.expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
537-
FileName::doc_test_source_code(PathBuf::from(path), line)
538-
}
539-
Err(_) => FileName::anon_source_code(&input),
540-
};
521+
);
522+
let line = isize::from_str_radix(&line, 10)
523+
.expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
524+
FileName::doc_test_source_code(PathBuf::from(path), line)
525+
}
526+
Err(_) => FileName::anon_source_code(&input),
527+
};
541528

542-
Ok(Some(Input::Str { name, input }))
529+
Ok(Some(Input::Str { name, input }))
530+
}
531+
[ifile] => Ok(Some(Input::File(PathBuf::from(ifile)))),
532+
[ifile1, ifile2, ..] => early_dcx.early_fatal(format!(
533+
"multiple input filenames provided (first two filenames are `{}` and `{}`)",
534+
ifile1, ifile2
535+
)),
536+
}
543537
}
544538

545539
/// Whether to stop or continue compilation.

Diff for: compiler/rustc_incremental/src/lib.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ mod persist;
1616

1717
pub use persist::{
1818
LoadResult, copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory,
19-
in_incr_comp_dir, in_incr_comp_dir_sess, load_query_result_cache, save_dep_graph,
20-
save_work_product_index, setup_dep_graph,
19+
in_incr_comp_dir, in_incr_comp_dir_sess, load_query_result_cache, save_work_product_index,
20+
setup_dep_graph,
2121
};
22+
use rustc_middle::util::Providers;
23+
24+
#[allow(missing_docs)]
25+
pub fn provide(providers: &mut Providers) {
26+
providers.hooks.save_dep_graph =
27+
|tcx| tcx.sess.time("serialize_dep_graph", || persist::save_dep_graph(tcx.tcx));
28+
}
2229

2330
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

Diff for: compiler/rustc_incremental/src/persist/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ mod work_product;
1212

1313
pub use fs::{finalize_session_directory, in_incr_comp_dir, in_incr_comp_dir_sess};
1414
pub use load::{LoadResult, load_query_result_cache, setup_dep_graph};
15-
pub use save::{save_dep_graph, save_work_product_index};
15+
pub(crate) use save::save_dep_graph;
16+
pub use save::save_work_product_index;
1617
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;

Diff for: compiler/rustc_incremental/src/persist/save.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::errors;
2525
///
2626
/// This function should only run after all queries have completed.
2727
/// Trying to execute a query afterwards would attempt to read the result cache we just dropped.
28-
pub fn save_dep_graph(tcx: TyCtxt<'_>) {
28+
pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) {
2929
debug!("save_dep_graph()");
3030
tcx.dep_graph.with_ignore(|| {
3131
let sess = tcx.sess;

Diff for: compiler/rustc_interface/src/passes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -689,10 +689,12 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
689689
rustc_const_eval::provide(providers);
690690
rustc_middle::hir::provide(providers);
691691
rustc_borrowck::provide(providers);
692+
rustc_incremental::provide(providers);
692693
rustc_mir_build::provide(providers);
693694
rustc_mir_transform::provide(providers);
694695
rustc_monomorphize::provide(providers);
695696
rustc_privacy::provide(providers);
697+
rustc_query_impl::provide(providers);
696698
rustc_resolve::provide(providers);
697699
rustc_hir_analysis::provide(providers);
698700
rustc_hir_typeck::provide(providers);

Diff for: compiler/rustc_interface/src/queries.rs

+7-25
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ use rustc_hir::def_id::LOCAL_CRATE;
1212
use rustc_middle::arena::Arena;
1313
use rustc_middle::dep_graph::DepGraph;
1414
use rustc_middle::ty::{GlobalCtxt, TyCtxt};
15-
use rustc_serialize::opaque::FileEncodeResult;
1615
use rustc_session::Session;
1716
use rustc_session::config::{self, OutputFilenames, OutputType};
1817

1918
use crate::errors::FailedWritingFile;
2019
use crate::interface::{Compiler, Result};
21-
use crate::{errors, passes};
20+
use crate::passes;
2221

2322
/// Represent the result of a query.
2423
///
@@ -62,7 +61,7 @@ impl<'a, T> std::ops::DerefMut for QueryResult<'a, T> {
6261

6362
impl<'a, 'tcx> QueryResult<'a, &'tcx GlobalCtxt<'tcx>> {
6463
pub fn enter<T>(&mut self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T {
65-
(*self.0).get_mut().enter(f)
64+
(*self.0).borrow().enter(f)
6665
}
6766
}
6867

@@ -90,8 +89,10 @@ impl<'tcx> Queries<'tcx> {
9089
}
9190
}
9291

93-
pub fn finish(&self) -> FileEncodeResult {
94-
if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) }
92+
pub fn finish(&'tcx self) {
93+
if let Some(gcx) = self.gcx_cell.get() {
94+
gcx.finish();
95+
}
9596
}
9697

9798
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
@@ -209,29 +210,10 @@ impl Compiler {
209210
let queries = Queries::new(self);
210211
let ret = f(&queries);
211212

212-
// NOTE: intentionally does not compute the global context if it hasn't been built yet,
213-
// since that likely means there was a parse error.
214-
if let Some(Ok(gcx)) = &mut *queries.gcx.result.borrow_mut() {
215-
let gcx = gcx.get_mut();
216-
// We assume that no queries are run past here. If there are new queries
217-
// after this point, they'll show up as "<unknown>" in self-profiling data.
218-
{
219-
let _prof_timer =
220-
queries.compiler.sess.prof.generic_activity("self_profile_alloc_query_strings");
221-
gcx.enter(rustc_query_impl::alloc_self_profile_query_strings);
222-
}
223-
224-
self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph));
225-
226-
gcx.enter(rustc_query_impl::query_key_hash_verify_all);
227-
}
228-
229213
// The timer's lifetime spans the dropping of `queries`, which contains
230214
// the global context.
231215
_timer = self.sess.timer("free_global_ctxt");
232-
if let Err((path, error)) = queries.finish() {
233-
self.sess.dcx().emit_fatal(errors::FailedWritingFile { path: &path, error });
234-
}
216+
queries.finish();
235217

236218
ret
237219
}

Diff for: compiler/rustc_middle/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ middle_drop_check_overflow =
7373
7474
middle_erroneous_constant = erroneous constant encountered
7575
76+
middle_failed_writing_file =
77+
failed to write file {$path}: {$error}"
78+
7679
middle_layout_references_error =
7780
the type has an unknown layout
7881

Diff for: compiler/rustc_middle/src/error.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::fmt;
2-
use std::path::PathBuf;
1+
use std::path::{Path, PathBuf};
2+
use std::{fmt, io};
33

44
use rustc_errors::codes::*;
55
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage};
@@ -18,6 +18,13 @@ pub struct DropCheckOverflow<'tcx> {
1818
pub overflow_ty: Ty<'tcx>,
1919
}
2020

21+
#[derive(Diagnostic)]
22+
#[diag(middle_failed_writing_file)]
23+
pub struct FailedWritingFile<'a> {
24+
pub path: &'a Path,
25+
pub error: io::Error,
26+
}
27+
2128
#[derive(Diagnostic)]
2229
#[diag(middle_opaque_hidden_type_mismatch)]
2330
pub struct OpaqueHiddenTypeMismatch<'tcx> {

Diff for: compiler/rustc_middle/src/hooks/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ declare_hooks! {
108108
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
109109
/// can just link to the upstream crate and therefore don't need a mono item.
110110
hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool;
111+
112+
hook alloc_self_profile_query_strings() -> ();
113+
114+
/// Saves and writes the DepGraph to the file system.
115+
///
116+
/// This function saves both the dep-graph and the query result cache,
117+
/// and drops the result cache.
118+
///
119+
/// This function should only run after all queries have completed.
120+
/// Trying to execute a query afterwards would attempt to read the result cache we just dropped.
121+
hook save_dep_graph() -> ();
122+
123+
hook query_key_hash_verify_all() -> ();
111124
}
112125

113126
#[cold]

Diff for: compiler/rustc_middle/src/ty/context.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -1371,8 +1371,17 @@ impl<'tcx> GlobalCtxt<'tcx> {
13711371
tls::enter_context(&icx, || f(icx.tcx))
13721372
}
13731373

1374-
pub fn finish(&self) -> FileEncodeResult {
1375-
self.dep_graph.finish_encoding()
1374+
pub fn finish(&'tcx self) {
1375+
// We assume that no queries are run past here. If there are new queries
1376+
// after this point, they'll show up as "<unknown>" in self-profiling data.
1377+
self.enter(|tcx| tcx.alloc_self_profile_query_strings());
1378+
1379+
self.enter(|tcx| tcx.save_dep_graph());
1380+
self.enter(|tcx| tcx.query_key_hash_verify_all());
1381+
1382+
if let Err((path, error)) = self.dep_graph.finish_encoding() {
1383+
self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error });
1384+
}
13761385
}
13771386
}
13781387

Diff for: compiler/rustc_query_impl/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,9 @@ pub fn query_system<'tcx>(
222222
}
223223

224224
rustc_middle::rustc_query_append! { define_queries! }
225+
226+
pub fn provide(providers: &mut rustc_middle::util::Providers) {
227+
providers.hooks.alloc_self_profile_query_strings =
228+
|tcx| alloc_self_profile_query_strings(tcx.tcx);
229+
providers.hooks.query_key_hash_verify_all = |tcx| query_key_hash_verify_all(tcx.tcx);
230+
}

Diff for: compiler/rustc_query_impl/src/profiling_support.rs

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
252252
return;
253253
}
254254

255+
let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings");
256+
255257
let mut string_cache = QueryKeyStringCache::new();
256258

257259
for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() {

0 commit comments

Comments
 (0)