diff --git a/Cargo.lock b/Cargo.lock index 9464c87fc728b..3776d562ff8cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3820,6 +3820,7 @@ dependencies = [ "rustc_interface", "rustc_lint", "rustc_log", + "rustc_macros", "rustc_metadata", "rustc_middle", "rustc_parse", diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 1802eedf193aa..0faf51b062b4c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -168,6 +168,13 @@ pub struct CodegenResults { pub crate_info: CrateInfo, } +pub enum CodegenErrors<'a> { + WrongFileType, + EmptyVersionNumber, + EncodingVersionMismatch { version_array: String, rlink_version: u32 }, + RustcVersionMismatch { rustc_version: String, current_version: &'a str }, +} + pub fn provide(providers: &mut Providers) { crate::back::symbol_export::provide(providers); crate::base::provide(providers); @@ -212,30 +219,34 @@ impl CodegenResults { encoder.finish() } - pub fn deserialize_rlink(data: Vec) -> Result { + pub fn deserialize_rlink<'a>(data: Vec) -> Result> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { - return Err("The input does not look like a .rlink file".to_string()); + return Err(CodegenErrors::WrongFileType); } let data = &data[RLINK_MAGIC.len()..]; if data.len() < 4 { - return Err("The input does not contain version number".to_string()); + return Err(CodegenErrors::EmptyVersionNumber); } let mut version_array: [u8; 4] = Default::default(); version_array.copy_from_slice(&data[..4]); if u32::from_be_bytes(version_array) != RLINK_VERSION { - return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string()); + return Err(CodegenErrors::EncodingVersionMismatch { + version_array: String::from_utf8_lossy(&version_array).to_string(), + rlink_version: RLINK_VERSION, + }); } let mut decoder = MemDecoder::new(&data[4..], 0); let rustc_version = decoder.read_str(); let current_version = RUSTC_VERSION.unwrap(); if rustc_version != current_version { - return Err(format!( - ".rlink file was produced by rustc version {rustc_version}, but the current version is {current_version}." - )); + return Err(CodegenErrors::RustcVersionMismatch { + rustc_version: rustc_version.to_string(), + current_version, + }); } let codegen_results = CodegenResults::decode(&mut decoder); diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 08d5d4f343c77..4570c1448337e 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -19,6 +19,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } +rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_parse = { path = "../rustc_parse" } rustc_plugin_impl = { path = "../rustc_plugin_impl" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index dac8df7dc55e0..a193d5db6916a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -9,6 +9,8 @@ #![feature(once_cell)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -16,7 +18,7 @@ extern crate tracing; pub extern crate rustc_plugin_impl as plugin; use rustc_ast as ast; -use rustc_codegen_ssa::{traits::CodegenBackend, CodegenResults}; +use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; @@ -56,6 +58,12 @@ use std::time::Instant; pub mod args; pub mod pretty; +mod session_diagnostics; + +use crate::session_diagnostics::{ + RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch, + RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead, +}; /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -581,18 +589,35 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp sess.init_crate_types(collect_crate_types(sess, &[])); let outputs = compiler.build_output_filenames(sess, &[]); let rlink_data = fs::read(file).unwrap_or_else(|err| { - sess.fatal(&format!("failed to read rlink file: {}", err)); + sess.emit_fatal(RlinkUnableToRead { err }); }); let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) { Ok(codegen) => codegen, - Err(error) => { - sess.fatal(&format!("Could not deserialize .rlink file: {error}")); + Err(err) => { + match err { + CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType), + CodegenErrors::EmptyVersionNumber => { + sess.emit_fatal(RLinkEmptyVersionNumber) + } + CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => { + sess.emit_fatal(RLinkEncodingVersionMismatch { + version_array, + rlink_version, + }) + } + CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => { + sess.emit_fatal(RLinkRustcVersionMismatch { + rustc_version, + current_version, + }) + } + }; } }; let result = compiler.codegen_backend().link(sess, codegen_results, &outputs); abort_on_err(result, sess); } else { - sess.fatal("rlink must be a file") + sess.emit_fatal(RlinkNotAFile {}) } Compilation::Stop } else { diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs new file mode 100644 index 0000000000000..fe64d0fca9b20 --- /dev/null +++ b/compiler/rustc_driver/src/session_diagnostics.rs @@ -0,0 +1,33 @@ +use rustc_macros::SessionDiagnostic; + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_unable_to_read)] +pub(crate) struct RlinkUnableToRead { + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_wrong_file_type)] +pub(crate) struct RLinkWrongFileType; + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_empty_version_number)] +pub(crate) struct RLinkEmptyVersionNumber; + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_encoding_version_mismatch)] +pub(crate) struct RLinkEncodingVersionMismatch { + pub version_array: String, + pub rlink_version: u32, +} + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_rustc_version_mismatch)] +pub(crate) struct RLinkRustcVersionMismatch<'a> { + pub rustc_version: String, + pub current_version: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(driver::rlink_no_a_file)] +pub(crate) struct RlinkNotAFile; diff --git a/compiler/rustc_error_messages/locales/en-US/driver.ftl b/compiler/rustc_error_messages/locales/en-US/driver.ftl new file mode 100644 index 0000000000000..73f084cf3290b --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/driver.ftl @@ -0,0 +1,11 @@ +driver_rlink_unable_to_read = failed to read rlink file: `{$err}` + +driver_rlink_wrong_file_type = The input does not look like a .rlink file + +driver_rlink_empty_version_number = The input does not contain version number + +driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` + +driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` + +driver_rlink_no_a_file = rlink must be a file diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 2d001d445be02..2ea07ca1a487a 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -36,6 +36,7 @@ fluent_messages! { borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl", + driver => "../locales/en-US/driver.ftl", expand => "../locales/en-US/expand.ftl", interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl",