Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ pub fn parse_remap_path_scope(
}

RemapPathScopeComponents::DOCUMENTATION
},
}
"debuginfo" => RemapPathScopeComponents::DEBUGINFO,
"coverage" => RemapPathScopeComponents::COVERAGE,
"object" => RemapPathScopeComponents::OBJECT,
Expand Down Expand Up @@ -1758,9 +1758,34 @@ fn parse_jobs_all(
check_upper_limit(frontend, opt_name);
frontend
}
None => None, // default to 1 thread irrespectively of `jobs` for now
None => {
// Build-time override to opt into a different default for the frontend thread count
if let Some(default_frontend_jobs) = option_env!("CFG_DEFAULT_FRONTEND_JOBS") {
let mut frontend_jobs = parse_jobs_one(
early_dcx,
"CFG_DEFAULT_FRONTEND_JOBS",
default_frontend_jobs,
true,
&mut available,
);

// CFG_DEFAULT_FRONTEND_JOBS is a build-time config, so we cannot use
// `check_upper_limit` here. Instead, we cap the frontend jobs to the value of
// --jobs, if it was passed and was smaller than the default frontend jobs
// count.
if let Some(jobs) = jobs
&& frontend_jobs.or(NonZero::new(1)) > jobs.or(NonZero::new(1))
{
frontend_jobs = jobs;
}
frontend_jobs
} else {
None // default to 1 thread irrespectively of `jobs` for now
}
}
},
};

let backend = match matches.opt_str("jobs-backend") {
Some(jobs_backend) => {
let opt_name = "--jobs-backend";
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,8 @@ fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelec
// We want to enable Polonius Alpha and Next Trait Solver by default on nighty
cargo.env("CFG_DEFAULT_POLONIUS_NEXT", "1");
cargo.env("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY", "1");
// Enable 2 threads for the parallel frontend by default on nightly
cargo.env("CFG_DEFAULT_FRONTEND_JOBS", "2");
}

// These conditionals represent a tension between three forces:
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/tests/compile-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ impl TestContext {
// FIXME(#160895): While the new solver is enabled by default on nightly,
// we don't want to use it in our tests for now.
"-Znext-solver=coherence",
// Run tests with the sequential frontend, for now, because the parallel frontend can
// produce non-deterministic order of diagnostics
"-Zthreads=1",
"-Dwarnings",
]
.map(OsString::from),
Expand Down
20 changes: 20 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,26 @@ impl<'test> TestCx<'test> {
rustc.arg(dir_opt);
};

if !self.config.parallel_frontend_enabled() {
// If the parallel frontend thread count was not specified, we override
// it to 1, because the tested toolchain might have a different default
// value for the frontend thread count, but we want to run tests in
// compiletest with the sequential frontend for now, until we prepare the testing
// infrastructure of all test suites to support potentially non-deterministic order of
// diagnostics.

// We can't set this option if the test already specifies the frontend thread count
// though.
if !self
.props
.compile_flags
.iter()
.any(|flag| flag.contains("-Zthreads") || flag.contains("--jobs-frontend"))
{
compiler.arg("-Zthreads=1");
}
}

match self.config.mode {
TestMode::Incremental => {
// If we are extracting and matching errors in the new
Expand Down
3 changes: 3 additions & 0 deletions src/tools/run-make-support/src/external_deps/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ impl Rustc {
cmd.arg(format!("-Zcodegen-backend={codegen_backend}"));
}

// Use a single frontend thread by default, for now
cmd.arg("-Zthreads=1");

// Automatically default to cross-compilation
Self { cmd, target: Some(target()) }
}
Expand Down
60 changes: 21 additions & 39 deletions tests/ui-fulldeps/obtain-borrowck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ extern crate rustc_interface;
extern crate rustc_middle;
extern crate rustc_session;

use std::cell::RefCell;
use std::collections::HashMap;
use std::process::ExitCode;
use std::thread_local;
use std::sync::{LazyLock, Mutex};

use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions};
use rustc_data_structures::fx::FxHashMap;
use rustc_borrowck::consumers::{self, ConsumerOptions, PoloniusInput};
use rustc_driver::Compilation;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
Expand Down Expand Up @@ -104,9 +102,9 @@ impl rustc_driver::Callbacks for CompilerCalls {
let mut bodies = get_bodies(tcx);
bodies.sort_by(|(def_id1, _), (def_id2, _)| def_id1.cmp(def_id2));
println!("Bodies retrieved for:");
for (def_id, body) in bodies {
for (def_id, facts) in bodies {
println!("{}", def_id);
assert!(body.input_facts.unwrap().cfg_edge.len() > 0);
assert!(facts.cfg_edge.len() > 0);
}

Compilation::Continue
Expand All @@ -118,47 +116,31 @@ fn override_queries(_session: &Session, local: &mut Providers) {
}

// Since mir_borrowck does not have access to any other state, we need to use a
// thread-local for storing the obtained MIR bodies.
//
// Note: We are using 'static lifetime here, which is in general unsound.
// Unfortunately, that is the only lifetime allowed here. Our use is safe
// because we cast it back to `'tcx` before using.
thread_local! {
pub static MIR_BODIES:
RefCell<HashMap<LocalDefId, BodyWithBorrowckFacts<'static>>> =
RefCell::new(HashMap::new());
}
// global variable for storing the obtained MIR bodies.
// Note that we don't use a thread-local variable, because borrowck can run under multiple threads.
pub static MIR_BODIES: LazyLock<Mutex<HashMap<LocalDefId, Option<Box<PoloniusInput>>>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));

fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> {
let opts = ConsumerOptions::PoloniusInputFacts;
let bodies_with_facts = consumers::get_bodies_with_borrowck_facts(tcx, def_id, opts);
// SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
let bodies_with_facts: FxHashMap<LocalDefId, BodyWithBorrowckFacts<'static>> =
unsafe { std::mem::transmute(bodies_with_facts) };
MIR_BODIES.with(|state| {
let mut map = state.borrow_mut();
for (def_id, body_with_facts) in bodies_with_facts {
assert!(map.insert(def_id, body_with_facts).is_none());
}
});
let mut map = MIR_BODIES.lock().unwrap();
for (def_id, body_with_facts) in bodies_with_facts {
assert!(map.insert(def_id, body_with_facts.input_facts).is_none());
}
let mut providers = Providers::default();
rustc_borrowck::provide(&mut providers.queries);
let original_mir_borrowck = providers.queries.mir_borrowck;
original_mir_borrowck(tcx, def_id)
}

/// Pull MIR bodies stored in the thread-local.
fn get_bodies<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<(String, BodyWithBorrowckFacts<'tcx>)> {
MIR_BODIES.with(|state| {
let mut map = state.borrow_mut();
map.drain()
.map(|(def_id, body)| {
let def_path = tcx.def_path(def_id.to_def_id());
// SAFETY: For soundness we need to ensure that the bodies have
// the same lifetime (`'tcx`), which they had before they were
// stored in the thread local.
(def_path.to_string_no_crate_verbose(), unsafe { std::mem::transmute(body) })
})
.collect()
})
/// Pull MIR bodies stored in the global variable.
fn get_bodies<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<(String, PoloniusInput)> {
let mut map = MIR_BODIES.lock().unwrap();
map.drain()
.map(|(def_id, facts)| {
let def_path = tcx.def_path(def_id.to_def_id());
(def_path.to_string_no_crate_verbose(), *facts.unwrap())
})
.collect()
}
Loading