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

View file

@ -20,7 +20,7 @@ use std::fs::{self, File};
use std::io::{self, IsTerminal, Read, Write}; use std::io::{self, IsTerminal, Read, Write};
use std::panic::{self, PanicHookInfo}; use std::panic::{self, PanicHookInfo};
use std::path::{Path, PathBuf}; 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::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Instant; 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 /// Variant of `catch_fatal_errors` for the `interface::Result` return type
/// that also computes the exit code. /// 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) { match catch_fatal_errors(f) {
Ok(()) => EXIT_SUCCESS, Ok(status) => status.report(),
_ => EXIT_FAILURE, _ => ExitCode::FAILURE,
} }
} }
@ -1670,7 +1670,7 @@ pub fn install_ctrlc_handler() {
.expect("Unable to install ctrlc handler"); .expect("Unable to install ctrlc handler");
} }
pub fn main() -> ! { pub fn main() -> ExitCode {
let start_time = Instant::now(); let start_time = Instant::now();
let start_rss = get_resident_set_size(); 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); 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::env::{self, VarError};
use std::io::{self, IsTerminal}; use std::io::{self, IsTerminal};
use std::path::Path; use std::path::Path;
use std::process; use std::process::ExitCode;
use rustc_errors::DiagCtxtHandle; use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::LOCAL_CRATE;
@ -126,7 +126,7 @@ mod visit;
mod visit_ast; mod visit_ast;
mod visit_lib; mod visit_lib;
pub fn main() { pub fn main() -> ExitCode {
let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
rustc_driver::install_ice_hook( rustc_driver::install_ice_hook(
@ -164,11 +164,10 @@ pub fn main() {
Err(error) => early_dcx.early_fatal(error.to_string()), 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); let at_args = rustc_driver::args::raw_args(&early_dcx);
main_args(&mut early_dcx, &at_args); main_args(&mut early_dcx, &at_args);
}); })
process::exit(exit_code);
} }
fn init_logging(early_dcx: &EarlyDiagCtxt) { fn init_logging(early_dcx: &EarlyDiagCtxt) {

View file

@ -32,7 +32,7 @@ use std::env;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::io::Write as _; use std::io::Write as _;
use std::path::Path; 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 /// 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`. /// 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() { 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"; 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()); let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
rustc_driver::init_rustc_env_logger(&early_dcx); rustc_driver::init_rustc_env_logger(&early_dcx);
@ -203,7 +205,7 @@ pub fn main() {
dcx.handle().note(format!("Clippy version: {version_info}")); 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 mut orig_args = rustc_driver::args::raw_args(&early_dcx);
let has_sysroot_arg = |args: &mut [String]| -> bool { 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); pass_sysroot_env_if_given(&mut args, sys_root_env);
rustc_driver::run_compiler(&args, &mut DefaultCallbacks); rustc_driver::run_compiler(&args, &mut DefaultCallbacks);
return; return ExitCode::SUCCESS;
} }
if orig_args.iter().any(|a| a == "--version" || a == "-V") { if orig_args.iter().any(|a| a == "--version" || a == "-V") {
let version_info = rustc_tools_util::get_version_info!(); let version_info = rustc_tools_util::get_version_info!();
match writeln!(&mut anstream::stdout().lock(), "{version_info}") { return match writeln!(&mut anstream::stdout().lock(), "{version_info}") {
Ok(()) => exit(rustc_driver::EXIT_SUCCESS), Ok(()) => ExitCode::SUCCESS,
Err(_) => exit(rustc_driver::EXIT_FAILURE), 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) { if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
display_help(); return display_help();
exit(0);
} }
let mut args: Vec<String> = orig_args.clone(); let mut args: Vec<String> = orig_args.clone();
@ -311,7 +312,8 @@ pub fn main() {
} else { } else {
rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var });
} }
})) ExitCode::SUCCESS
})
} }
#[must_use] #[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`. // We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
#![feature(rustc_private)] #![feature(rustc_private)]
fn main() { use std::process::ExitCode;
fn main() -> ExitCode {
rustdoc::main() rustdoc::main()
} }

View file

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