Return ExitCode from rustc_driver::main

This makes rustc simply return an exit code from main rather than calling `std::process::exit` with an exit code. This means that drops run normally and the process exits cleanly.

Also instead of hard coding success and failure codes this uses `ExitCode::SUCCESS` and `ExitCode::FAILURE`, which in turn effectively uses `libc::EXIT_SUCCESS` and `libc::EXIT_FAILURE` (via std). These are `0` and `1` respectively for all currently supported host platforms so it doesn't actually change the exit code.
This commit is contained in:
Chris Denton 2025-12-25 10:51:54 +00:00
parent d222ddc4d9
commit 6d36c8a5fc
No known key found for this signature in database
GPG key ID: 713472F2F45627DE
6 changed files with 34 additions and 29 deletions

View file

@ -3,6 +3,8 @@
// Several crates are depended upon but unused so that they are present in the sysroot
#![expect(unused_crate_dependencies)]
use std::process::ExitCode;
// A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]`
// mechanism. However, for complicated reasons (see
@ -38,6 +40,6 @@
#[cfg(feature = "jemalloc")]
use tikv_jemalloc_sys as _;
fn main() {
fn main() -> ExitCode {
rustc_driver::main()
}

View file

@ -20,7 +20,7 @@ use std::fs::{self, File};
use std::io::{self, IsTerminal, Read, Write};
use std::panic::{self, PanicHookInfo};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use std::process::{Command, ExitCode, Stdio, Termination};
use std::sync::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Instant;
@ -1382,10 +1382,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
/// Variant of `catch_fatal_errors` for the `interface::Result` return type
/// that also computes the exit code.
pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 {
pub fn catch_with_exit_code<T: Termination>(f: impl FnOnce() -> T) -> ExitCode {
match catch_fatal_errors(f) {
Ok(()) => EXIT_SUCCESS,
_ => EXIT_FAILURE,
Ok(status) => status.report(),
_ => ExitCode::FAILURE,
}
}
@ -1670,7 +1670,7 @@ pub fn install_ctrlc_handler() {
.expect("Unable to install ctrlc handler");
}
pub fn main() -> ! {
pub fn main() -> ExitCode {
let start_time = Instant::now();
let start_rss = get_resident_set_size();
@ -1690,5 +1690,5 @@ pub fn main() -> ! {
print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss, format);
}
process::exit(exit_code)
exit_code
}

View file

@ -71,7 +71,7 @@ extern crate tikv_jemalloc_sys as _;
use std::env::{self, VarError};
use std::io::{self, IsTerminal};
use std::path::Path;
use std::process;
use std::process::ExitCode;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::LOCAL_CRATE;
@ -126,7 +126,7 @@ mod visit;
mod visit_ast;
mod visit_lib;
pub fn main() {
pub fn main() -> ExitCode {
let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
rustc_driver::install_ice_hook(
@ -164,11 +164,10 @@ pub fn main() {
Err(error) => early_dcx.early_fatal(error.to_string()),
}
let exit_code = rustc_driver::catch_with_exit_code(|| {
rustc_driver::catch_with_exit_code(|| {
let at_args = rustc_driver::args::raw_args(&early_dcx);
main_args(&mut early_dcx, &at_args);
});
process::exit(exit_code);
})
}
fn init_logging(early_dcx: &EarlyDiagCtxt) {

View file

@ -32,7 +32,7 @@ use std::env;
use std::fs::read_to_string;
use std::io::Write as _;
use std::path::Path;
use std::process::exit;
use std::process::ExitCode;
/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
@ -182,15 +182,17 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
}
}
fn display_help() {
fn display_help() -> ExitCode {
if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() {
exit(rustc_driver::EXIT_FAILURE);
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml";
pub fn main() {
pub fn main() -> ExitCode {
let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
rustc_driver::init_rustc_env_logger(&early_dcx);
@ -203,7 +205,7 @@ pub fn main() {
dcx.handle().note(format!("Clippy version: {version_info}"));
});
exit(rustc_driver::catch_with_exit_code(move || {
rustc_driver::catch_with_exit_code(move || {
let mut orig_args = rustc_driver::args::raw_args(&early_dcx);
let has_sysroot_arg = |args: &mut [String]| -> bool {
@ -246,15 +248,15 @@ pub fn main() {
pass_sysroot_env_if_given(&mut args, sys_root_env);
rustc_driver::run_compiler(&args, &mut DefaultCallbacks);
return;
return ExitCode::SUCCESS;
}
if orig_args.iter().any(|a| a == "--version" || a == "-V") {
let version_info = rustc_tools_util::get_version_info!();
match writeln!(&mut anstream::stdout().lock(), "{version_info}") {
Ok(()) => exit(rustc_driver::EXIT_SUCCESS),
Err(_) => exit(rustc_driver::EXIT_FAILURE),
return match writeln!(&mut anstream::stdout().lock(), "{version_info}") {
Ok(()) => ExitCode::SUCCESS,
Err(_) => ExitCode::FAILURE,
}
}
@ -268,8 +270,7 @@ pub fn main() {
}
if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
display_help();
exit(0);
return display_help();
}
let mut args: Vec<String> = orig_args.clone();
@ -311,7 +312,8 @@ pub fn main() {
} else {
rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var });
}
}))
ExitCode::SUCCESS
})
}
#[must_use]

View file

@ -1,6 +1,8 @@
// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
#![feature(rustc_private)]
fn main() {
use std::process::ExitCode;
fn main() -> ExitCode {
rustdoc::main()
}

View file

@ -28,6 +28,7 @@ extern crate rustc_session;
use std::cell::RefCell;
use std::collections::HashMap;
use std::process::ExitCode;
use std::thread_local;
use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions};
@ -42,16 +43,15 @@ use rustc_middle::ty::TyCtxt;
use rustc_middle::util::Providers;
use rustc_session::Session;
fn main() {
let exit_code = rustc_driver::catch_with_exit_code(move || {
fn main() -> ExitCode {
rustc_driver::catch_with_exit_code(move || {
let mut rustc_args: Vec<_> = std::env::args().collect();
// We must pass -Zpolonius so that the borrowck information is computed.
rustc_args.push("-Zpolonius".to_owned());
let mut callbacks = CompilerCalls::default();
// Call the Rust compiler with our callbacks.
rustc_driver::run_compiler(&rustc_args, &mut callbacks);
});
std::process::exit(exit_code);
})
}
#[derive(Default)]