diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9233287cf3a75..2440f20502ab1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -187,6 +187,12 @@ impl Display for RegionName { } } +impl rustc_errors::IntoDiagnosticArg for RegionName { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId { self.body.source.def_id().expect_local() diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index b2d92d0dba7a4..c71413e8e7c04 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -369,6 +369,8 @@ pub(super) fn dump_mir_results<'tcx>( }; } +#[allow(rustc::diagnostic_outside_of_impl)] +#[allow(rustc::untranslatable_diagnostic)] pub(super) fn dump_annotation<'tcx>( infcx: &InferCtxt<'tcx>, body: &Body<'tcx>, diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 23acf159240fa..13199d0385255 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -1,4 +1,4 @@ -use rustc_errors::{IntoDiagnosticArg, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; @@ -128,18 +128,6 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { }, } -impl IntoDiagnosticArg for &RegionName { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - format!("{}", self).into_diagnostic_arg() - } -} - -impl IntoDiagnosticArg for RegionName { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - format!("{}", self).into_diagnostic_arg() - } -} - #[derive(Subdiagnostic)] pub(crate) enum RequireStaticErr { #[note(borrowck_used_impl_require_static)] diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index bf1da38312f7d..5ab87feb98b11 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -200,6 +200,7 @@ unsafe impl Sync for GccContext {} impl WriteBackendMethods for GccCodegenBackend { type Module = GccContext; type TargetMachine = (); + type TargetMachineError = (); type ModuleBuffer = ModuleBuffer; type ThinData = (); type ThinBuffer = ThinBuffer; diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 6c0faf37a63ce..d2e01708a37bc 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,5 +1,7 @@ use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers}; -use crate::errors::DynamicLinkingWithLTO; +use crate::errors::{ + DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, +}; use crate::llvm::{self, build_string}; use crate::{LlvmCodegenBackend, ModuleLlvm}; use object::read::archive::ArchiveFile; @@ -77,15 +79,12 @@ fn prepare_lto( // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { - let e = diag_handler.fatal( - "lto can only be run for executables, cdylibs and \ - static library outputs", - ); - return Err(e); + diag_handler.emit_err(LtoDisallowed); + return Err(FatalError); } else if *crate_type == CrateType::Dylib { if !cgcx.opts.unstable_opts.dylib_lto { - return Err(diag_handler - .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`")); + diag_handler.emit_err(LtoDylib); + return Err(FatalError); } } } @@ -127,7 +126,10 @@ fn prepare_lto( let module = SerializedModule::FromRlib(data.to_vec()); upstream_modules.push((module, CString::new(name).unwrap())); } - Err(msg) => return Err(diag_handler.fatal(&msg)), + Err(e) => { + diag_handler.emit_err(e); + return Err(FatalError); + } } } } @@ -140,7 +142,7 @@ fn prepare_lto( Ok((symbols_below_threshold, upstream_modules)) } -fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> { +fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> { let mut len = 0; let data = unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) }; @@ -155,8 +157,9 @@ fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> { Ok(bc) } else { assert!(len == 0); - let msg = llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()); - Err(format!("failed to get bitcode from object file for LTO ({})", msg)) + Err(LtoBitcodeFromRlib { + llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()), + }) } } @@ -328,10 +331,9 @@ fn fat_lto( }); info!("linking {:?}", name); let data = bc_decoded.data(); - linker.add(data).map_err(|()| { - let msg = format!("failed to load bitcode of module {:?}", name); - write::llvm_err(diag_handler, &msg) - })?; + linker + .add(data) + .map_err(|()| write::llvm_err(diag_handler, LlvmError::LoadBitcode { name }))?; serialized_bitcode.push(bc_decoded); } drop(linker); @@ -489,7 +491,7 @@ fn thin_lto( symbols_below_threshold.as_ptr(), symbols_below_threshold.len() as u32, ) - .ok_or_else(|| write::llvm_err(diag_handler, "failed to prepare thin LTO context"))?; + .ok_or_else(|| write::llvm_err(diag_handler, LlvmError::PrepareThinLtoContext))?; let data = ThinData(data); @@ -562,8 +564,7 @@ fn thin_lto( // session, overwriting the previous serialized data (if any). if let Some(path) = key_map_path { if let Err(err) = curr_key_map.save_to_file(&path) { - let msg = format!("Error while writing ThinLTO key data: {}", err); - return Err(write::llvm_err(diag_handler, &msg)); + return Err(write::llvm_err(diag_handler, LlvmError::WriteThinLtoKey { err })); } } @@ -689,8 +690,7 @@ pub unsafe fn optimize_thin_module( let module_name = &thin_module.shared.module_names[thin_module.idx]; let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap()); - let tm = - (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?; + let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, e))?; // Right now the implementation we've got only works over serialized // modules, so we create a fresh new LLVM context and parse the module @@ -717,8 +717,7 @@ pub unsafe fn optimize_thin_module( let mut cu2 = ptr::null_mut(); llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); if !cu2.is_null() { - let msg = "multiple source DICompileUnits found"; - return Err(write::llvm_err(&diag_handler, msg)); + return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit)); } // Up next comes the per-module local analyses that we do for Thin LTO. @@ -733,8 +732,7 @@ pub unsafe fn optimize_thin_module( let _timer = cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)); + return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule)); } save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); } @@ -744,8 +742,7 @@ pub unsafe fn optimize_thin_module( .prof .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)); + return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule)); } save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve"); } @@ -755,8 +752,7 @@ pub unsafe fn optimize_thin_module( .prof .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)); + return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule)); } save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize"); } @@ -765,8 +761,7 @@ pub unsafe fn optimize_thin_module( let _timer = cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)); + return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule)); } save_temp_bitcode(cgcx, &module, "thin-lto-after-import"); } @@ -886,11 +881,7 @@ pub fn parse_module<'a>( diag_handler: &Handler, ) -> Result<&'a llvm::Module, FatalError> { unsafe { - llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else( - || { - let msg = "failed to parse bitcode for LTO module"; - write::llvm_err(diag_handler, msg) - }, - ) + llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()) + .ok_or_else(|| write::llvm_err(diag_handler, LlvmError::ParseBitcode)) } } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index b2af9f31e4494..38f8733763dfa 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -5,6 +5,9 @@ use crate::back::profiling::{ use crate::base; use crate::common; use crate::consts; +use crate::errors::{ + CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode, +}; use crate::llvm::{self, DiagnosticInfo, PassManager}; use crate::llvm_util; use crate::type_::Type; @@ -37,10 +40,10 @@ use std::slice; use std::str; use std::sync::Arc; -pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError { +pub fn llvm_err<'a>(handler: &rustc_errors::Handler, err: LlvmError<'a>) -> FatalError { match llvm::last_error() { - Some(err) => handler.fatal(&format!("{}: {}", msg, err)), - None => handler.fatal(msg), + Some(llvm_err) => handler.emit_almost_fatal(WithLlvmError(err, llvm_err)), + None => handler.emit_almost_fatal(err), } } @@ -85,10 +88,9 @@ pub fn write_output_file<'ll>( } } - result.into_result().map_err(|()| { - let msg = format!("could not write output to {}", output.display()); - llvm_err(handler, &msg) - }) + result + .into_result() + .map_err(|()| llvm_err(handler, LlvmError::WriteOutput { path: output })) } } @@ -98,7 +100,7 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm: // system/tcx is set up. let features = llvm_util::global_llvm_features(sess, false); target_machine_factory(sess, config::OptLevel::No, &features)(config) - .unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise()) + .unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise()) } pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { @@ -117,7 +119,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll tcx.backend_optimization_level(()), tcx.global_backend_features(()), )(config) - .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise()) + .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), err).raise()) } pub fn to_llvm_opt_settings( @@ -240,9 +242,7 @@ pub fn target_machine_factory( ) }; - tm.ok_or_else(|| { - format!("Could not create LLVM TargetMachine for triple: {}", triple.to_str().unwrap()) - }) + tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() }) }) } @@ -355,25 +355,28 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void }; if enabled { - diag_handler.note_without_error(&format!( - "{}:{}:{}: {}: {}", - opt.filename, opt.line, opt.column, opt.pass_name, opt.message, - )); + diag_handler.emit_note(FromLlvmOptimizationDiag { + filename: &opt.filename, + line: opt.line, + column: opt.column, + pass_name: &opt.pass_name, + message: &opt.message, + }); } } llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => { - let msg = llvm::build_string(|s| { + let message = llvm::build_string(|s| { llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) }) .expect("non-UTF8 diagnostic"); - diag_handler.warn(&msg); + diag_handler.emit_warning(FromLlvmDiag { message }); } llvm::diagnostic::Unsupported(diagnostic_ref) => { - let msg = llvm::build_string(|s| { + let message = llvm::build_string(|s| { llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) }) .expect("non-UTF8 diagnostic"); - diag_handler.err(&msg); + diag_handler.emit_err(FromLlvmDiag { message }); } llvm::diagnostic::UnknownDiagnostic(..) => {} } @@ -494,7 +497,7 @@ pub(crate) unsafe fn llvm_optimize( llvm_plugins.as_ptr().cast(), llvm_plugins.len(), ); - result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes")) + result.into_result().map_err(|()| llvm_err(diag_handler, LlvmError::RunLlvmPasses)) } // Unsafe due to LLVM calls. @@ -547,8 +550,7 @@ pub(crate) fn link( let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name); let buffer = ModuleBuffer::new(module.module_llvm.llmod()); linker.add(buffer.data()).map_err(|()| { - let msg = format!("failed to serialize module {:?}", module.name); - llvm_err(diag_handler, &msg) + llvm_err(diag_handler, LlvmError::SerializeModule { name: &module.name }) })?; } drop(linker); @@ -626,9 +628,8 @@ pub(crate) unsafe fn codegen( let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name); - if let Err(e) = fs::write(&bc_out, data) { - let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e); - diag_handler.err(&msg); + if let Err(err) = fs::write(&bc_out, data) { + diag_handler.emit_err(WriteBytecode { path: &bc_out, err }); } } @@ -678,10 +679,9 @@ pub(crate) unsafe fn codegen( record_artifact_size(&cgcx.prof, "llvm_ir", &out); } - result.into_result().map_err(|()| { - let msg = format!("failed to write LLVM IR to {}", out.display()); - llvm_err(diag_handler, &msg) - })?; + result + .into_result() + .map_err(|()| llvm_err(diag_handler, LlvmError::WriteIr { path: &out }))?; } if config.emit_asm { @@ -749,8 +749,8 @@ pub(crate) unsafe fn codegen( EmitObj::Bitcode => { debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(e) = link_or_copy(&bc_out, &obj_out) { - diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + if let Err(err) = link_or_copy(&bc_out, &obj_out) { + diag_handler.emit_err(CopyBitcode { err }); } if !config.emit_bc { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 001d1ce93d8b4..81072edc475c4 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -1,10 +1,11 @@ use std::borrow::Cow; +use std::ffi::CString; +use std::path::Path; -use rustc_errors::fluent; -use rustc_errors::DiagnosticBuilder; -use rustc_errors::ErrorGuaranteed; -use rustc_errors::Handler; -use rustc_errors::IntoDiagnostic; +use rustc_data_structures::small_c_str::SmallCStr; +use rustc_errors::{ + fluent, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -81,10 +82,18 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { #[note] pub(crate) struct DynamicLinkingWithLTO; -#[derive(Diagnostic)] -#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)] -pub(crate) struct FailParsingTargetMachineConfigToTargetMachine { - pub error: String, +pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); + +impl IntoDiagnostic<'_, EM> for ParseTargetMachineConfig<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> { + let diag: DiagnosticBuilder<'_, EM> = self.0.into_diagnostic(sess); + let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message"); + let message = sess.eagerly_translate_to_string(message.clone(), diag.args()); + + let mut diag = sess.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config); + diag.set_arg("error", message); + diag + } } pub(crate) struct TargetFeatureDisableOrEnable<'a> { @@ -110,3 +119,99 @@ impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { diag } } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_lto_disallowed)] +pub(crate) struct LtoDisallowed; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_lto_dylib)] +pub(crate) struct LtoDylib; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_lto_bitcode_from_rlib)] +pub(crate) struct LtoBitcodeFromRlib { + pub llvm_err: String, +} + +#[derive(Diagnostic)] +pub enum LlvmError<'a> { + #[diag(codegen_llvm_write_output)] + WriteOutput { path: &'a Path }, + #[diag(codegen_llvm_target_machine)] + CreateTargetMachine { triple: SmallCStr }, + #[diag(codegen_llvm_run_passes)] + RunLlvmPasses, + #[diag(codegen_llvm_serialize_module)] + SerializeModule { name: &'a str }, + #[diag(codegen_llvm_write_ir)] + WriteIr { path: &'a Path }, + #[diag(codegen_llvm_prepare_thin_lto_context)] + PrepareThinLtoContext, + #[diag(codegen_llvm_load_bitcode)] + LoadBitcode { name: CString }, + #[diag(codegen_llvm_write_thinlto_key)] + WriteThinLtoKey { err: std::io::Error }, + #[diag(codegen_llvm_multiple_source_dicompileunit)] + MultipleSourceDiCompileUnit, + #[diag(codegen_llvm_prepare_thin_lto_module)] + PrepareThinLtoModule, + #[diag(codegen_llvm_parse_bitcode)] + ParseBitcode, +} + +pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); + +impl IntoDiagnostic<'_, EM> for WithLlvmError<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> { + use LlvmError::*; + let msg_with_llvm_err = match &self.0 { + WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, + CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err, + RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err, + SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err, + WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err, + PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err, + LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err, + WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err, + MultipleSourceDiCompileUnit => { + fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err + } + PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, + ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, + }; + let mut diag = self.0.into_diagnostic(sess); + diag.set_primary_message(msg_with_llvm_err); + diag.set_arg("llvm_err", self.1); + diag + } +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_from_llvm_optimization_diag)] +pub(crate) struct FromLlvmOptimizationDiag<'a> { + pub filename: &'a str, + pub line: std::ffi::c_uint, + pub column: std::ffi::c_uint, + pub pass_name: &'a str, + pub message: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_from_llvm_diag)] +pub(crate) struct FromLlvmDiag { + pub message: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_write_bytecode)] +pub(crate) struct WriteBytecode<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_copy_bitcode)] +pub(crate) struct CopyBitcode { + pub err: std::io::Error, +} diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 246e82545c874..111d14b265cde 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -5,11 +5,12 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(extern_types)] #![feature(hash_raw_entry)] +#![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(extern_types)] +#![feature(never_type)] #![feature(once_cell)] -#![feature(iter_intersperse)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -22,7 +23,7 @@ extern crate tracing; use back::write::{create_informational_target_machine, create_target_machine}; -use errors::FailParsingTargetMachineConfigToTargetMachine; +use errors::ParseTargetMachineConfig; pub use llvm_util::target_features; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; @@ -169,6 +170,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { type Module = ModuleLlvm; type ModuleBuffer = back::lto::ModuleBuffer; type TargetMachine = &'static mut llvm::TargetMachine; + type TargetMachineError = crate::errors::LlvmError<'static>; type ThinData = back::lto::ThinData; type ThinBuffer = back::lto::ThinBuffer; fn print_pass_timings(&self) { @@ -416,8 +418,7 @@ impl ModuleLlvm { let tm = match (cgcx.tm_factory)(tm_factory_config) { Ok(m) => m, Err(e) => { - handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e }); - return Err(FatalError); + return Err(handler.emit_almost_fatal(ParseTargetMachineConfig(e))); } }; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9f1614af7b16c..8508ab87532c2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -305,8 +305,12 @@ impl TargetMachineFactoryConfig { } pub type TargetMachineFactoryFn = Arc< - dyn Fn(TargetMachineFactoryConfig) -> Result<::TargetMachine, String> - + Send + dyn Fn( + TargetMachineFactoryConfig, + ) -> Result< + ::TargetMachine, + ::TargetMachineError, + > + Send + Sync, >; diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index e0e8ffa89ed15..9826256a4c5d5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -8,6 +8,7 @@ use rustc_middle::dep_graph::WorkProduct; pub trait WriteBackendMethods: 'static + Sized + Clone { type Module: Send + Sync; type TargetMachine; + type TargetMachineError; type ModuleBuffer: ModuleBufferMethods; type ThinData: Send + Sync; type ThinBuffer: ThinBufferMethods; diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index ccefd6adaf14b..02e0b042ad263 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -43,7 +43,6 @@ use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use rustc_target::json::ToJson; -use std::borrow::Cow; use std::cmp::max; use std::env; use std::ffi::OsString; @@ -1205,29 +1204,20 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { handler.emit_diagnostic(&mut d); } - let mut xs: Vec> = vec![ - "the compiler unexpectedly panicked. this is a bug.".into(), - format!("we would appreciate a bug report: {bug_report_url}").into(), - format!( - "rustc {} running on {}", - util::version_str!().unwrap_or("unknown_version"), - config::host_triple() - ) - .into(), - ]; + handler.emit_note(session_diagnostics::Ice); + handler.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + handler.emit_note(session_diagnostics::IceVersion { + version: util::version_str!().unwrap_or("unknown_version"), + triple: config::host_triple(), + }); if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { - xs.push(format!("compiler flags: {}", flags.join(" ")).into()); - + handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") }); if excluded_cargo_defaults { - xs.push("some of the compiler flags provided by cargo are hidden".into()); + handler.emit_note(session_diagnostics::IceExcludeCargoDefaults); } } - for note in &xs { - handler.note_without_error(note.as_ref()); - } - // If backtraces are enabled, also print the query stack let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0"); diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs index c1bc10891144c..a7aef9cbc2c8a 100644 --- a/compiler/rustc_driver/src/session_diagnostics.rs +++ b/compiler/rustc_driver/src/session_diagnostics.rs @@ -38,3 +38,30 @@ pub(crate) struct UnprettyDumpFail { pub path: String, pub err: String, } + +#[derive(Diagnostic)] +#[diag(driver_ice)] +pub(crate) struct Ice; + +#[derive(Diagnostic)] +#[diag(driver_ice_bug_report)] +pub(crate) struct IceBugReport<'a> { + pub bug_report_url: &'a str, +} + +#[derive(Diagnostic)] +#[diag(driver_ice_version)] +pub(crate) struct IceVersion<'a> { + pub version: &'a str, + pub triple: &'a str, +} + +#[derive(Diagnostic)] +#[diag(driver_ice_flags)] +pub(crate) struct IceFlags { + pub flags: String, +} + +#[derive(Diagnostic)] +#[diag(driver_ice_exclude_cargo_defaults)] +pub(crate) struct IceExcludeCargoDefaults; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index b82c903290b9a..e5df417370bb9 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -39,5 +39,51 @@ codegen_llvm_dynamic_linking_with_lto = cannot prefer dynamic linking when performing LTO .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO -codegen_llvm_fail_parsing_target_machine_config_to_target_machine = +codegen_llvm_parse_target_machine_config = failed to parse target machine config to target machine: {$error} + +codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs + +codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` + +codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err}) + +codegen_llvm_write_output = could not write output to {$path} +codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err} + +codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple} +codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} + +codegen_llvm_run_passes = failed to run LLVM passes +codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err} + +codegen_llvm_serialize_module = failed to serialize module {$name} +codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err} + +codegen_llvm_write_ir = failed to write LLVM IR to {$path} +codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err} + +codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context +codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err} + +codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" +codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} + +codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err} +codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err} + +codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found +codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err} + +codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module +codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err} + +codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module +codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err} + +codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name}: {$message} +codegen_llvm_from_llvm_diag = {$message} + +codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} + +codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err} diff --git a/compiler/rustc_error_messages/locales/en-US/driver.ftl b/compiler/rustc_error_messages/locales/en-US/driver.ftl index 8ad198c86c933..79ffc82c6c67d 100644 --- a/compiler/rustc_error_messages/locales/en-US/driver.ftl +++ b/compiler/rustc_error_messages/locales/en-US/driver.ftl @@ -11,3 +11,9 @@ driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version driver_rlink_no_a_file = rlink must be a file driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}` + +driver_ice = the compiler unexpectedly panicked. this is a bug. +driver_ice_bug_report = we would appreciate a bug report: {$bug_report_url} +driver_ice_version = rustc {$version} running on {$triple} +driver_ice_flags = compiler flags: {$flags} +driver_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_error_messages/locales/en-US/expand.ftl index df0e8ae5dd8f5..dbd80954382db 100644 --- a/compiler/rustc_error_messages/locales/en-US/expand.ftl +++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl @@ -127,3 +127,5 @@ expand_module_file_not_found = expand_module_multiple_candidates = file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}" .help = delete or rename one of them to remove the ambiguity + +expand_trace_macro = trace_macro diff --git a/compiler/rustc_error_messages/locales/en-US/incremental.ftl b/compiler/rustc_error_messages/locales/en-US/incremental.ftl new file mode 100644 index 0000000000000..4852ee0d9595c --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/incremental.ftl @@ -0,0 +1,118 @@ +incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} + +incremental_missing_depnode = missing `DepNode` variant + +incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected + +incremental_no_path = no path from `{$source}` to `{$target}` + +incremental_ok = OK + +incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified + +incremental_missing_query_depgraph = + found CGU-reuse attribute but `-Zquery-dep-graph` was not specified + +incremental_malformed_cgu_name = + found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case). + +incremental_no_module_named = + no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} + +incremental_field_associated_value_expected = associated value expected for `{$name}` + +incremental_no_field = no field `{$name}` + +incremental_assertion_auto = + `except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\" + +incremental_undefined_clean_dirty_assertions_item = + clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} + +incremental_undefined_clean_dirty_assertions = + clean/dirty auto-assertions not yet defined for {$kind} + +incremental_repeated_depnode_label = dep-node label `{$label}` is repeated + +incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized + +incremental_not_dirty = `{$dep_node_str}` should be dirty but is not + +incremental_not_clean = `{$dep_node_str}` should be clean but is not + +incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not + +incremental_unknown_item = unknown item `{$name}` + +incremental_no_cfg = no cfg attribute + +incremental_associated_value_expected_for = associated value expected for `{$ident}` + +incremental_associated_value_expected = expected an associated value + +incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute + +incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err} + +incremental_create_new = failed to create {$name} at `{$path}`: {$err} + +incremental_write_new = failed to write {$name} to `{$path}`: {$err} + +incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err} + +incremental_create_incr_comp_dir = + could not create incremental compilation {$tag} directory `{$path}`: {$err} + +incremental_create_lock = + incremental compilation: could not create session directory lock file: {$lock_err} +incremental_lock_unsupported = + the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation +incremental_cargo_help_1 = + incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental) +incremental_cargo_help_2 = + the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir) + +incremental_delete_lock = + error deleting lock file for incremental compilation session directory `{$path}`: {$err} + +incremental_hard_link_failed = + hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}` + +incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err} + +incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} + +incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err} + +incremental_invalid_gc_failed = + failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err} + +incremental_finalized_gc_failed = + failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err} + +incremental_session_gc_failed = + failed to garbage collect incremental compilation session directory `{$path}`: {$err} + +incremental_assert_not_loaded = + we asserted that the incremental cache should not be loaded, but it was loaded + +incremental_assert_loaded = + we asserted that an existing incremental cache directory should be successfully loaded, but it was not + +incremental_delete_incompatible = + failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err} + +incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err} + +incremental_decode_incr_cache = could not decode incremental cache: {$err} + +incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err} + +incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err} + +incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err} + +incremental_copy_workproduct_to_cache = + error copying object file `{$from}` to incremental directory as `{$to}`: {$err} + +incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err} diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index 688b044722260..a7bc0e7af1fe9 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -44,3 +44,13 @@ interface_failed_writing_file = interface_proc_macro_crate_panic_abort = building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic + +interface_unsupported_crate_type_for_target = + dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` + +interface_multiple_output_types_adaption = + due to multiple output types requested, the explicitly specified output file name will be adapted for each output type + +interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag + +interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl index 243d10bfa0621..6cea6a603f336 100644 --- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -24,3 +24,9 @@ monomorphize_large_assignments = monomorphize_couldnt_dump_mono_stats = unexpected error occurred while dumping monomorphization stats: {$error} + +monomorphize_encountered_error_while_instantiating = + the above error was encountered while instantiating `{$formatted_item}` + +monomorphize_unknown_cgu_collection_mode = + unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 0c2ab3d08f9de..6ebb188288f00 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -731,3 +731,5 @@ passes_proc_macro_missing_args = mismatched {$kind} signature passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"` passes_proc_macro_unsafe = proc macro functions may not be `unsafe` + +passes_skipping_const_checks = skipping const checks diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index bc37d91a7c6af..5984c201af0d0 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -89,3 +89,5 @@ session_int_literal_too_large = integer literal is too large session_invalid_int_literal_width = invalid width `{$width}` for integer literal .help = valid widths are 8, 16, 32, 64 and 128 + +session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index f053bdc3809be..1882d4b698e61 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -52,6 +52,7 @@ fluent_messages! { expand => "../locales/en-US/expand.ftl", hir_analysis => "../locales/en-US/hir_analysis.ftl", hir_typeck => "../locales/en-US/hir_typeck.ftl", + incremental => "../locales/en-US/incremental.ftl", infer => "../locales/en-US/infer.ftl", interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 4ad24c1400d69..df949e46fbde5 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1051,6 +1051,7 @@ impl Diagnostic { ) -> ( &Level, &[(DiagnosticMessage, Style)], + Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, &Option, &MultiSpan, &Result, SuggestionsDisabled>, @@ -1059,6 +1060,7 @@ impl Diagnostic { ( &self.level, &self.message, + self.args().collect(), &self.code, &self.span, &self.suggestions, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index cbfee582d871f..c9d662ad43fe5 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -408,6 +408,59 @@ impl EmissionGuarantee for ! { } } +impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + #[track_caller] + pub(crate) fn new_almost_fatal( + handler: &'a Handler, + message: impl Into, + ) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); + Self::new_diagnostic_almost_fatal(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub(crate) fn new_diagnostic_almost_fatal( + handler: &'a Handler, + diagnostic: Diagnostic, + ) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for rustc_span::fatal_error::FatalError { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + // Then fatally error.. + rustc_span::fatal_error::FatalError + } + + fn make_diagnostic_builder( + handler: &Handler, + msg: impl Into, + ) -> DiagnosticBuilder<'_, Self> { + DiagnosticBuilder::new_almost_fatal(handler, msg) + } +} + /// In general, the `DiagnosticBuilder` uses deref to allow access to /// the fields and methods of the embedded `diagnostic` in a /// transparent way. *However,* many of the methods are intended to diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index dad5e98aac021..7a94ce3777a29 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -36,6 +36,12 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> { } } +impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.clone().into_diagnostic_arg() + } +} + macro_rules! into_diagnostic_arg_using_display { ($( $ty:ty ),+ $(,)?) => { $( @@ -153,12 +159,6 @@ impl IntoDiagnosticArg for ast::Path { } } -impl IntoDiagnosticArg for &ast::Path { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self))) - } -} - impl IntoDiagnosticArg for ast::token::Token { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(pprust::token_to_string(&self)) @@ -177,6 +177,18 @@ impl IntoDiagnosticArg for type_ir::FloatTy { } } +impl IntoDiagnosticArg for std::ffi::CString { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) + } +} + +impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) + } +} + impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index d076fc08b0e2f..ec04e865d53b1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -617,22 +617,24 @@ impl Handler { } } - /// Translate `message` eagerly with `args`. + /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. pub fn eagerly_translate<'a>( &self, message: DiagnosticMessage, args: impl Iterator>, ) -> SubdiagnosticMessage { + SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args)) + } + + /// Translate `message` eagerly with `args` to `String`. + pub fn eagerly_translate_to_string<'a>( + &self, + message: DiagnosticMessage, + args: impl Iterator>, + ) -> String { let inner = self.inner.borrow(); let args = crate::translation::to_fluent_args(args); - SubdiagnosticMessage::Eager( - inner - .emitter - .translate_message(&message, &args) - .map_err(Report::new) - .unwrap() - .to_string(), - ) + inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() } // This is here to not allow mutation of flags; @@ -1010,6 +1012,7 @@ impl Handler { } #[track_caller] + #[rustc_lint_diagnostics] pub fn span_note_without_error( &self, span: impl Into, @@ -1019,6 +1022,7 @@ impl Handler { } #[track_caller] + #[rustc_lint_diagnostics] pub fn span_note_diag( &self, span: Span, @@ -1030,19 +1034,23 @@ impl Handler { } // NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread + #[rustc_lint_diagnostics] pub fn fatal(&self, msg: impl Into) -> FatalError { self.inner.borrow_mut().fatal(msg) } + #[rustc_lint_diagnostics] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.inner.borrow_mut().err(msg) } + #[rustc_lint_diagnostics] pub fn warn(&self, msg: impl Into) { let mut db = DiagnosticBuilder::new(self, Warning(None), msg); db.emit(); } + #[rustc_lint_diagnostics] pub fn note_without_error(&self, msg: impl Into) { DiagnosticBuilder::new(self, Note, msg).emit(); } @@ -1059,6 +1067,7 @@ impl Handler { pub fn has_errors(&self) -> Option { if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None } } + pub fn has_errors_or_lint_errors(&self) -> Option { if self.inner.borrow().has_errors_or_lint_errors() { Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) @@ -1132,6 +1141,20 @@ impl Handler { self.create_warning(warning).emit() } + pub fn create_almost_fatal<'a>( + &'a self, + fatal: impl IntoDiagnostic<'a, FatalError>, + ) -> DiagnosticBuilder<'a, FatalError> { + fatal.into_diagnostic(self) + } + + pub fn emit_almost_fatal<'a>( + &'a self, + fatal: impl IntoDiagnostic<'a, FatalError>, + ) -> FatalError { + self.create_almost_fatal(fatal).emit() + } + pub fn create_fatal<'a>( &'a self, fatal: impl IntoDiagnostic<'a, !>, @@ -1157,6 +1180,17 @@ impl Handler { self.create_bug(bug).emit() } + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + self.create_note(note).emit() + } + + pub fn create_note<'a>( + &'a self, + note: impl IntoDiagnostic<'a, Noted>, + ) -> DiagnosticBuilder<'a, Noted> { + note.into_diagnostic(self) + } + fn emit_diag_at_span( &self, mut diag: Diagnostic, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 951d59246785d..5a48473d5b07c 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -4,7 +4,7 @@ use crate::errors::{ ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord, AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid, MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord, - ResolveRelativePath, TakesNoArguments, + ResolveRelativePath, TakesNoArguments, TraceMacro, }; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -1142,8 +1142,8 @@ impl<'a> ExtCtxt<'a> { self.sess.parse_sess.span_diagnostic.span_bug(sp, msg); } pub fn trace_macros_diag(&mut self) { - for (sp, notes) in self.expansions.iter() { - let mut db = self.sess.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro"); + for (span, notes) in self.expansions.iter() { + let mut db = self.sess.parse_sess.create_note(TraceMacro { span: *span }); for note in notes { db.note(note); } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index afe5169d3f5c0..9b9697ab13d26 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -368,3 +368,10 @@ pub(crate) struct ModuleMultipleCandidates { pub default_path: String, pub secondary_path: String, } + +#[derive(Diagnostic)] +#[diag(expand_trace_macro)] +pub struct TraceMacro { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 6703d53f3805c..22bd12f2e6361 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -33,6 +33,7 @@ //! fn baz() { foo(); } //! ``` +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING}; @@ -133,12 +134,10 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); - } + Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode { + span: attr.span, + name: n, + }), } } }; @@ -149,16 +148,14 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); - } + Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode { + span: attr.span, + name: n, + }), } } None => { - self.tcx.sess.span_fatal(attr.span, "missing DepNode variant"); + self.tcx.sess.emit_fatal(errors::MissingDepNode { span: attr.span }); } }; self.then_this_would_need.push(( @@ -204,7 +201,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou // Return early here so as not to construct the query, which is not cheap. if if_this_changed.is_empty() { for &(target_span, _, _, _) in then_this_would_need { - tcx.sess.span_err(target_span, "no `#[rustc_if_this_changed]` annotation detected"); + tcx.sess.emit_err(errors::MissingIfThisChanged { span: target_span }); } return; } @@ -213,16 +210,13 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou let dependents = query.transitive_predecessors(source_dep_node); for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { if !dependents.contains(&target_dep_node) { - tcx.sess.span_err( - target_span, - &format!( - "no path from `{}` to `{}`", - tcx.def_path_str(source_def_id), - target_pass - ), - ); + tcx.sess.emit_err(errors::NoPath { + span: target_span, + source: tcx.def_path_str(source_def_id), + target: *target_pass, + }); } else { - tcx.sess.span_err(target_span, "OK"); + tcx.sess.emit_err(errors::Ok { span: target_span }); } } } diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index 89d419bc8e90f..2968a0e1203a9 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -22,6 +22,7 @@ //! allows for doing a more fine-grained check to see if pre- or post-lto data //! was re-used. +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::LOCAL_CRATE; @@ -66,10 +67,9 @@ impl<'tcx> AssertModuleSource<'tcx> { sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), other => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unknown cgu-reuse-kind `{}` specified", other), - ); + self.tcx + .sess + .emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other }); } } } else { @@ -77,10 +77,7 @@ impl<'tcx> AssertModuleSource<'tcx> { }; if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.tcx.sess.span_fatal( - attr.span, - "found CGU-reuse attribute but `-Zquery-dep-graph` was not specified", - ); + self.tcx.sess.emit_fatal(errors::MissingQueryDepGraph { span: attr.span }); } if !self.check_config(attr) { @@ -92,13 +89,11 @@ impl<'tcx> AssertModuleSource<'tcx> { let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string(); if !user_path.starts_with(&crate_name) { - let msg = format!( - "Found malformed codegen unit name `{}`. \ - Codegen units names must always start with the name of the \ - crate (`{}` in this case).", - user_path, crate_name - ); - self.tcx.sess.span_fatal(attr.span, &msg); + self.tcx.sess.emit_fatal(errors::MalformedCguName { + span: attr.span, + user_path, + crate_name, + }); } // Split of the "special suffix" if there is one. @@ -125,15 +120,12 @@ impl<'tcx> AssertModuleSource<'tcx> { let mut cgu_names: Vec<&str> = self.available_cgus.iter().map(|cgu| cgu.as_str()).collect(); cgu_names.sort(); - self.tcx.sess.span_err( - attr.span, - &format!( - "no module named `{}` (mangled: {}). Available modules: {}", - user_path, - cgu_name, - cgu_names.join(", ") - ), - ); + self.tcx.sess.emit_err(errors::NoModuleNamed { + span: attr.span, + user_path, + cgu_name, + cgu_names: cgu_names.join(", "), + }); } self.tcx.sess.cgu_reuse_tracker.set_expectation( @@ -151,15 +143,15 @@ impl<'tcx> AssertModuleSource<'tcx> { if let Some(value) = item.value_str() { return value; } else { - self.tcx.sess.span_fatal( - item.span(), - &format!("associated value expected for `{}`", name), - ); + self.tcx.sess.emit_fatal(errors::FieldAssociatedValueExpected { + span: item.span(), + name, + }); } } } - self.tcx.sess.span_fatal(attr.span, &format!("no field `{}`", name)); + self.tcx.sess.emit_fatal(errors::NoField { span: attr.span, name }); } /// Scan for a `cfg="foo"` attribute and check whether we have a diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs new file mode 100644 index 0000000000000..deb8767836543 --- /dev/null +++ b/compiler/rustc_incremental/src/errors.rs @@ -0,0 +1,364 @@ +use rustc_macros::Diagnostic; +use rustc_span::{symbol::Ident, Span, Symbol}; +use std::path::{Path, PathBuf}; + +#[derive(Diagnostic)] +#[diag(incremental_unrecognized_depnode)] +pub struct UnrecognizedDepNode { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(incremental_missing_depnode)] +pub struct MissingDepNode { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_missing_if_this_changed)] +pub struct MissingIfThisChanged { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_ok)] +pub struct Ok { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_no_path)] +pub struct NoPath { + #[primary_span] + pub span: Span, + pub target: Symbol, + pub source: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_unknown_reuse_kind)] +pub struct UnknownReuseKind { + #[primary_span] + pub span: Span, + pub kind: Symbol, +} + +#[derive(Diagnostic)] +#[diag(incremental_missing_query_depgraph)] +pub struct MissingQueryDepGraph { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_malformed_cgu_name)] +pub struct MalformedCguName { + #[primary_span] + pub span: Span, + pub user_path: String, + pub crate_name: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_no_module_named)] +pub struct NoModuleNamed<'a> { + #[primary_span] + pub span: Span, + pub user_path: &'a str, + pub cgu_name: Symbol, + pub cgu_names: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_field_associated_value_expected)] +pub struct FieldAssociatedValueExpected { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(incremental_no_field)] +pub struct NoField { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(incremental_assertion_auto)] +pub struct AssertionAuto<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, + pub e: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_undefined_clean_dirty_assertions_item)] +pub struct UndefinedCleanDirtyItem { + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_undefined_clean_dirty_assertions)] +pub struct UndefinedCleanDirty { + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_repeated_depnode_label)] +pub struct RepeatedDepNodeLabel<'a> { + #[primary_span] + pub span: Span, + pub label: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_unrecognized_depnode_label)] +pub struct UnrecognizedDepNodeLabel<'a> { + #[primary_span] + pub span: Span, + pub label: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_not_dirty)] +pub struct NotDirty<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_not_clean)] +pub struct NotClean<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_not_loaded)] +pub struct NotLoaded<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag(incremental_unknown_item)] +pub struct UnknownItem { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(incremental_no_cfg)] +pub struct NoCfg { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_associated_value_expected_for)] +pub struct AssociatedValueExpectedFor { + #[primary_span] + pub span: Span, + pub ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(incremental_associated_value_expected)] +pub struct AssociatedValueExpected { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_unchecked_clean)] +pub struct UncheckedClean { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(incremental_delete_old)] +pub struct DeleteOld<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_create_new)] +pub struct CreateNew<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_write_new)] +pub struct WriteNew<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_canonicalize_path)] +pub struct CanonicalizePath { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_create_incr_comp_dir)] +pub struct CreateIncrCompDir<'a> { + pub tag: &'a str, + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_create_lock)] +pub struct CreateLock<'a> { + pub lock_err: std::io::Error, + pub session_dir: &'a Path, + #[note(incremental_lock_unsupported)] + pub is_unsupported_lock: Option<()>, + #[help(incremental_cargo_help_1)] + #[help(incremental_cargo_help_2)] + pub is_cargo: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(incremental_delete_lock)] +pub struct DeleteLock<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_hard_link_failed)] +pub struct HardLinkFailed<'a> { + pub path: &'a Path, +} + +#[derive(Diagnostic)] +#[diag(incremental_delete_partial)] +pub struct DeletePartial<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_delete_full)] +pub struct DeleteFull<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_finalize)] +pub struct Finalize<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_invalid_gc_failed)] +pub struct InvalidGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_finalized_gc_failed)] +pub struct FinalizedGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_session_gc_failed)] +pub struct SessionGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_assert_not_loaded)] +pub struct AssertNotLoaded; + +#[derive(Diagnostic)] +#[diag(incremental_assert_loaded)] +pub struct AssertLoaded; + +#[derive(Diagnostic)] +#[diag(incremental_delete_incompatible)] +pub struct DeleteIncompatible { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_load_dep_graph)] +pub struct LoadDepGraph { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_decode_incr_cache)] +pub struct DecodeIncrCache { + pub err: String, +} + +#[derive(Diagnostic)] +#[diag(incremental_write_dep_graph)] +pub struct WriteDepGraph<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_move_dep_graph)] +pub struct MoveDepGraph<'a> { + pub from: &'a Path, + pub to: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_create_dep_graph)] +pub struct CreateDepGraph<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_copy_workproduct_to_cache)] +pub struct CopyWorkProductToCache<'a> { + pub from: &'a Path, + pub to: &'a Path, + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(incremental_delete_workproduct)] +pub struct DeleteWorkProduct<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 83dd9a67e61bc..3c58cfa38f280 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,8 +2,11 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -12,6 +15,7 @@ extern crate tracing; mod assert_dep_graph; pub mod assert_module_sources; +mod errors; mod persist; use assert_dep_graph::assert_dep_graph; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index ed7b272b13d17..c6e63998c7935 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -19,6 +19,7 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. +use crate::errors; use rustc_ast::{self as ast, Attribute, NestedMetaItem}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::LocalDefId; @@ -196,11 +197,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let loaded_from_disk = self.loaded_from_disk(attr); for e in except.iter() { if !auto.remove(e) { - let msg = format!( - "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"", - name, e - ); - self.tcx.sess.span_fatal(attr.span, &msg); + self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e }); } } Assertion { clean: auto, dirty: except, loaded_from_disk } @@ -282,14 +279,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { // An implementation, eg `impl Trait for Foo { .. }` HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL), - _ => self.tcx.sess.span_fatal( - attr.span, - &format!( - "clean/dirty auto-assertions not yet defined \ - for Node::Item.node={:?}", - item.kind - ), - ), + _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirtyItem { + span: attr.span, + kind: format!("{:?}", item.kind), + }), } } HirNode::TraitItem(item) => match item.kind { @@ -302,10 +295,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), }, - _ => self.tcx.sess.span_fatal( - attr.span, - &format!("clean/dirty auto-assertions not yet defined for {:?}", node), - ), + _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirty { + span: attr.span, + kind: format!("{:?}", node), + }), }; let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); @@ -318,16 +311,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let label = label.trim(); if DepNode::has_label_string(label) { if out.contains(label) { - self.tcx.sess.span_fatal( - item.span(), - &format!("dep-node label `{}` is repeated", label), - ); + self.tcx + .sess + .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label }); } out.insert(label.to_string()); } else { self.tcx .sess - .span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label)); + .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label }); } } out @@ -348,7 +340,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess - .span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str)); + .emit_err(errors::NotDirty { span: item_span, dep_node_str: &dep_node_str }); } } @@ -359,7 +351,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess - .span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str)); + .emit_err(errors::NotClean { span: item_span, dep_node_str: &dep_node_str }); } } @@ -368,10 +360,9 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) { let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` should have been loaded from disk but it was not", dep_node_str), - ); + self.tcx + .sess + .emit_err(errors::NotLoaded { span: item_span, dep_node_str: &dep_node_str }); } } @@ -412,12 +403,12 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { - tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty())); + tcx.sess.emit_err(errors::UnknownItem { span: attr.span, name: item.name_or_empty() }); } } match cfg { - None => tcx.sess.span_fatal(attr.span, "no cfg attribute"), + None => tcx.sess.emit_fatal(errors::NoCfg { span: attr.span }), Some(c) => c, } } @@ -426,13 +417,11 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { if let Some(value) = item.value_str() { value } else { - let msg = if let Some(ident) = item.ident() { - format!("associated value expected for `{}`", ident) + if let Some(ident) = item.ident() { + tcx.sess.emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); } else { - "expected an associated value".to_string() - }; - - tcx.sess.span_fatal(item.span(), &msg); + tcx.sess.emit_fatal(errors::AssociatedValueExpected { span: item.span() }); + } } } @@ -456,7 +445,7 @@ impl<'tcx> FindAllAttrs<'tcx> { fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { for attr in &self.found_attrs { if !checked_attrs.contains(&attr.id) { - self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute"); + self.tcx.sess.emit_err(errors::UncheckedClean { span: attr.span }); checked_attrs.insert(attr.id); } } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 2dbd4b6bce85a..dc981c6179eeb 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -9,15 +9,15 @@ //! compiler versions don't change frequently for the typical user, being //! conservative here practically has no downside. -use std::env; -use std::fs; -use std::io::{self, Read}; -use std::path::{Path, PathBuf}; - +use crate::errors; use rustc_data_structures::memmap::Mmap; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encoder; use rustc_session::Session; +use std::env; +use std::fs; +use std::io::{self, Read}; +use std::path::{Path, PathBuf}; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; @@ -60,12 +60,7 @@ where } Err(err) if err.kind() == io::ErrorKind::NotFound => (), Err(err) => { - sess.err(&format!( - "unable to delete old {} at `{}`: {}", - name, - path_buf.display(), - err - )); + sess.emit_err(errors::DeleteOld { name, path: path_buf, err }); return; } } @@ -73,7 +68,7 @@ where let mut encoder = match FileEncoder::new(&path_buf) { Ok(encoder) => encoder, Err(err) => { - sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err)); + sess.emit_err(errors::CreateNew { name, path: path_buf, err }); return; } }; @@ -90,7 +85,7 @@ where debug!("save: data written to disk successfully"); } Err(err) => { - sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err)); + sess.emit_err(errors::WriteNew { name, path: path_buf, err }); } } } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 1fd2b9b0d7b7b..73d7e3becab48 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -103,6 +103,7 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. +use crate::errors; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; @@ -225,12 +226,7 @@ pub fn prepare_session_directory( let crate_dir = match crate_dir.canonicalize() { Ok(v) => v, Err(err) => { - let reported = sess.err(&format!( - "incremental compilation: error canonicalizing path `{}`: {}", - crate_dir.display(), - err - )); - return Err(reported); + return Err(sess.emit_err(errors::CanonicalizePath { path: crate_dir, err })); } }; @@ -273,14 +269,7 @@ pub fn prepare_session_directory( debug!("successfully copied data from: {}", source_directory.display()); if !allows_links { - sess.warn(&format!( - "Hard linking files in the incremental \ - compilation cache failed. Copying files \ - instead. Consider moving the cache \ - directory to a file system which supports \ - hard linking in session dir `{}`", - session_dir.display() - )); + sess.emit_warning(errors::HardLinkFailed { path: &session_dir }); } sess.init_incr_comp_session(session_dir, directory_lock, true); @@ -295,12 +284,7 @@ pub fn prepare_session_directory( // Try to remove the session directory we just allocated. We don't // know if there's any garbage in it from the failed copy action. if let Err(err) = safe_remove_dir_all(&session_dir) { - sess.warn(&format!( - "Failed to delete partly initialized \ - session dir `{}`: {}", - session_dir.display(), - err - )); + sess.emit_warning(errors::DeletePartial { path: &session_dir, err }); } delete_session_dir_lock_file(sess, &lock_file_path); @@ -332,12 +316,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { ); if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) { - sess.warn(&format!( - "Error deleting incremental compilation \ - session directory `{}`: {}", - incr_comp_session_dir.display(), - err - )); + sess.emit_warning(errors::DeleteFull { path: &incr_comp_session_dir, err }); } let lock_file_path = lock_file_path(&*incr_comp_session_dir); @@ -380,12 +359,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { } Err(e) => { // Warn about the error. However, no need to abort compilation now. - sess.warn(&format!( - "Error finalizing incremental compilation \ - session directory `{}`: {}", - incr_comp_session_dir.display(), - e - )); + sess.emit_warning(errors::Finalize { path: &incr_comp_session_dir, err: e }); debug!("finalize_session_directory() - error, marking as invalid"); // Drop the file lock, so we can garage collect @@ -488,16 +462,7 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua debug!("{} directory created successfully", dir_tag); Ok(()) } - Err(err) => { - let reported = sess.err(&format!( - "Could not create incremental compilation {} \ - directory `{}`: {}", - dir_tag, - path.display(), - err - )); - Err(reported) - } + Err(err) => Err(sess.emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })), } } @@ -518,46 +483,20 @@ fn lock_directory( // the lock should be exclusive Ok(lock) => Ok((lock, lock_file_path)), Err(lock_err) => { - let mut err = sess.struct_err(&format!( - "incremental compilation: could not create \ - session directory lock file: {}", - lock_err - )); - if flock::Lock::error_unsupported(&lock_err) { - err.note(&format!( - "the filesystem for the incremental path at {} \ - does not appear to support locking, consider changing the \ - incremental path to a filesystem that supports locking \ - or disable incremental compilation", - session_dir.display() - )); - if std::env::var_os("CARGO").is_some() { - err.help( - "incremental compilation can be disabled by setting the \ - environment variable CARGO_INCREMENTAL=0 (see \ - https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)", - ); - err.help( - "the entire build directory can be changed to a different \ - filesystem by setting the environment variable CARGO_TARGET_DIR \ - to a different path (see \ - https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)", - ); - } - } - Err(err.emit()) + let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(()); + Err(sess.emit_err(errors::CreateLock { + lock_err, + session_dir, + is_unsupported_lock, + is_cargo: std::env::var_os("CARGO").map(|_| ()), + })) } } } fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) { if let Err(err) = safe_remove_file(&lock_file_path) { - sess.warn(&format!( - "Error deleting lock file for incremental \ - compilation session directory `{}`: {}", - lock_file_path.display(), - err - )); + sess.emit_warning(errors::DeleteLock { path: lock_file_path, err }); } } @@ -774,12 +713,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { if !lock_file_to_session_dir.values().any(|dir| *dir == directory_name) { let path = crate_directory.join(directory_name); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect invalid incremental \ - compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::InvalidGcFailed { path: &path, err }); } } } @@ -885,12 +819,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect finalized incremental \ - compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::FinalizedGcFailed { path: &path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(&path)); } @@ -907,11 +836,7 @@ fn delete_old(sess: &Session, path: &Path) { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect incremental compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::SessionGcFailed { path: &path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(&path)); } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 1c5fd91690230..d5097065dda2e 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -1,5 +1,6 @@ //! Code to save/load the dep-graph from files. +use crate::errors; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; @@ -8,7 +9,7 @@ use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; use rustc_session::Session; -use std::path::Path; +use std::path::{Path, PathBuf}; use super::data::*; use super::file_format; @@ -27,11 +28,10 @@ pub enum LoadResult { }, /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - /// An error occurred. - Error { - #[allow(missing_docs)] - message: String, - }, + /// Loading the dep graph failed. + LoadDepGraph(PathBuf, std::io::Error), + /// Decoding loaded incremental cache failed. + DecodeIncrCache(Box), } impl LoadResult { @@ -40,36 +40,31 @@ impl LoadResult { // Check for errors when using `-Zassert-incremental-state` match (sess.opts.assert_incr_state, &self) { (Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => { - sess.fatal( - "We asserted that the incremental cache should not be loaded, \ - but it was loaded.", - ); + sess.emit_fatal(errors::AssertNotLoaded); } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::Error { .. } | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) + | LoadResult::DecodeIncrCache(..) + | LoadResult::DataOutOfDate, ) => { - sess.fatal( - "We asserted that an existing incremental cache directory should \ - be successfully loaded, but it was not.", - ); + sess.emit_fatal(errors::AssertLoaded); } _ => {} }; match self { - LoadResult::Error { message } => { - sess.warn(&message); + LoadResult::LoadDepGraph(path, err) => { + sess.emit_warning(errors::LoadDepGraph { path, err }); + Default::default() + } + LoadResult::DecodeIncrCache(err) => { + sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") }); Default::default() } LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { - sess.err(&format!( - "Failed to delete invalidated or incompatible \ - incremental compilation session directory contents `{}`: {}.", - dep_graph_path(sess).display(), - err - )); + sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err }); } Default::default() } @@ -90,9 +85,7 @@ fn load_data( // compiler version. Neither is an error. LoadResult::DataOutOfDate } - Err(err) => LoadResult::Error { - message: format!("could not load dep-graph from `{}`: {}", path.display(), err), - }, + Err(err) => LoadResult::LoadDepGraph(path.to_path_buf(), err), } } @@ -114,9 +107,9 @@ impl MaybeAsync> { pub fn open(self) -> LoadResult { match self { MaybeAsync::Sync(result) => result, - MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error { - message: format!("could not decode incremental cache: {:?}", e), - }), + MaybeAsync::Async(handle) => { + handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e)) + } } } } @@ -185,7 +178,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { match load_data(report_incremental_info, &path, nightly_build) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, - LoadResult::Error { message } => LoadResult::Error { message }, + LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), + LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), LoadResult::Ok { data: (bytes, start_pos) } => { let mut decoder = MemDecoder::new(&bytes, start_pos); let prev_commandline_args_hash = u64::decode(&mut decoder); diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 6e9dcdd981ec4..27be56eac6f99 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; @@ -59,19 +60,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { move || { sess.time("incr_comp_persist_dep_graph", || { if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) { - sess.err(&format!( - "failed to write dependency graph to `{}`: {}", - staging_dep_graph_path.display(), - err - )); + sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err }); } if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { - sess.err(&format!( - "failed to move dependency graph from `{}` to `{}`: {}", - staging_dep_graph_path.display(), - dep_graph_path.display(), - err - )); + sess.emit_err(errors::MoveDepGraph { + from: &staging_dep_graph_path, + to: &dep_graph_path, + err, + }); } }); }, @@ -163,11 +159,7 @@ pub fn build_dep_graph( let mut encoder = match FileEncoder::new(&path_buf) { Ok(encoder) => encoder, Err(err) => { - sess.err(&format!( - "failed to create dependency graph at `{}`: {}", - path_buf.display(), - err - )); + sess.emit_err(errors::CreateDepGraph { path: &path_buf, err }); return None; } }; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 2f1853c441eee..dc98fbeb0d166 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -2,6 +2,7 @@ //! //! [work products]: WorkProduct +use crate::errors; use crate::persist::fs::*; use rustc_data_structures::fx::FxHashMap; use rustc_fs_util::link_or_copy; @@ -28,12 +29,11 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let _ = saved_files.insert(ext.to_string(), file_name); } Err(err) => { - sess.warn(&format!( - "error copying object file `{}` to incremental directory as `{}`: {}", - path.display(), - path_in_incr_dir.display(), - err - )); + sess.emit_warning(errors::CopyWorkProductToCache { + from: &path, + to: &path_in_incr_dir, + err, + }); } } } @@ -49,11 +49,7 @@ pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { for (_, path) in &work_product.saved_files { let path = in_incr_comp_dir_sess(sess, path); if let Err(err) = std_fs::remove_file(&path) { - sess.warn(&format!( - "file-system error deleting outdated file `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::DeleteWorkProduct { path: &path, err }); } } } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index f817c5bc1cd73..1199ff287c430 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -49,9 +49,6 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -[dev-dependencies] -rustc_target = { path = "../rustc_target" } - [features] llvm = ['rustc_codegen_llvm'] rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler'] diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 15d7e977bbe88..29543fe2f932c 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,5 +1,7 @@ use rustc_macros::Diagnostic; +use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_target::spec::TargetTriple; use std::io; use std::path::Path; @@ -91,3 +93,22 @@ pub struct FailedWritingFile<'a> { #[derive(Diagnostic)] #[diag(interface_proc_macro_crate_panic_abort)] pub struct ProcMacroCratePanicAbort; + +#[derive(Diagnostic)] +#[diag(interface_unsupported_crate_type_for_target)] +pub struct UnsupportedCrateTypeForTarget<'a> { + pub crate_type: CrateType, + pub target_triple: &'a TargetTriple, +} + +#[derive(Diagnostic)] +#[diag(interface_multiple_output_types_adaption)] +pub struct MultipleOutputTypesAdaption; + +#[derive(Diagnostic)] +#[diag(interface_ignoring_extra_filename)] +pub struct IgnoringExtraFilename; + +#[derive(Diagnostic)] +#[diag(interface_ignoring_out_dir)] +pub struct IgnoringOutDir; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 54363e07b971a..e4b4d5375e64a 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,3 +1,4 @@ +use crate::errors; use info; use libloading::Library; use rustc_ast as ast; @@ -472,16 +473,15 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Outpu let unnamed_output_types = sess.opts.output_types.values().filter(|a| a.is_none()).count(); let ofile = if unnamed_output_types > 1 { - sess.warn( - "due to multiple output types requested, the explicitly specified \ - output file name will be adapted for each output type", - ); + sess.emit_warning(errors::MultipleOutputTypesAdaption); None } else { if !sess.opts.cg.extra_filename.is_empty() { - sess.warn("ignoring -C extra-filename flag due to -o flag"); + sess.emit_warning(errors::IgnoringExtraFilename); } Some(out_file.clone()) }; if sess.io.output_dir != None { - sess.warn("ignoring --out-dir flag due to -o flag"); + sess.emit_warning(errors::IgnoringOutDir); } OutputFilenames::new( diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 305f0427e501b..31a3ffbb1d891 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -201,7 +201,9 @@ use rustc_target::abi::Size; use std::ops::Range; use std::path::PathBuf; -use crate::errors::{LargeAssignmentsLint, RecursionLimit, TypeLengthLimit}; +use crate::errors::{ + EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit, +}; #[derive(PartialEq)] pub enum MonoItemCollectionMode { @@ -524,10 +526,10 @@ fn collect_items_rec<'tcx>( && starting_point.node.is_user_defined() { let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string()); - tcx.sess.span_note_without_error( - starting_point.span, - &format!("the above error was encountered while instantiating `{formatted_item}`"), - ); + tcx.sess.emit_note(EncounteredErrorWhileInstantiating { + span: starting_point.span, + formatted_item, + }); } inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 5233cfb21203b..a53bd7e1fef5e 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -83,3 +83,17 @@ pub struct SymbolAlreadyDefined { pub struct CouldntDumpMonoStats { pub error: String, } + +#[derive(Diagnostic)] +#[diag(monomorphize_encountered_error_while_instantiating)] +pub struct EncounteredErrorWhileInstantiating { + #[primary_span] + pub span: Span, + pub formatted_item: String, +} + +#[derive(Diagnostic)] +#[diag(monomorphize_unknown_cgu_collection_mode)] +pub struct UnknownCguCollectionMode<'a> { + pub mode: &'a str, +} diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index fd6bcad18983a..af3f60bb9326d 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -114,7 +114,9 @@ use rustc_span::symbol::Symbol; use crate::collector::InliningMap; use crate::collector::{self, MonoItemCollectionMode}; -use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy}; +use crate::errors::{ + CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy, +}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -348,17 +350,13 @@ where fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) { let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items { Some(ref s) => { - let mode_string = s.to_lowercase(); - let mode_string = mode_string.trim(); - if mode_string == "eager" { + let mode = s.to_lowercase(); + let mode = mode.trim(); + if mode == "eager" { MonoItemCollectionMode::Eager } else { - if mode_string != "lazy" { - let message = format!( - "Unknown codegen-item collection mode '{mode_string}'. \ - Falling back to 'lazy' mode." - ); - tcx.sess.warn(&message); + if mode != "lazy" { + tcx.sess.emit_warning(UnknownCguCollectionMode { mode }); } MonoItemCollectionMode::Lazy diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index dd8c646a43c82..526b829bf676a 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; -use crate::errors::ExprNotAllowedInContext; +use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks}; /// An expression that is not *always* legal in a const context. #[derive(Clone, Copy)] @@ -124,7 +124,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { // corresponding feature gate. This encourages nightly users to use feature gates when // possible. None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => { - tcx.sess.span_warn(span, "skipping const checks"); + tcx.sess.emit_warning(SkippingConstChecks { span }); return; } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9e05ad22e6241..97169a6367c3d 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1565,3 +1565,10 @@ pub(crate) struct ProcMacroUnsafe { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(passes_skipping_const_checks)] +pub struct SkippingConstChecks { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c49c5fa990413..973d860118ef1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -24,7 +24,7 @@ use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::{ColorConfig, HandlerFlags}; +use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg}; use std::collections::btree_map::{ Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, @@ -2694,6 +2694,12 @@ impl fmt::Display for CrateType { } } +impl IntoDiagnosticArg for CrateType { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { /// `-Zunpretty=normal` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index f5a72573d58cd..8e8fba5e236f5 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -375,3 +375,9 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: } } } + +#[derive(Diagnostic)] +#[diag(session_optimization_fuel_exhausted)] +pub struct OptimisationFuelExhausted { + pub msg: String, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 95f199de6ff6f..91d23f1041fe9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -5,9 +5,10 @@ use crate::config::Input; use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath}; use crate::errors::{ BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, - LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist, - ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, - SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, + LinkerPluginToWindowsNotSupported, NotCircumventFeature, OptimisationFuelExhausted, + ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, SanitizerCfiEnabled, + SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks, + SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, }; @@ -483,6 +484,8 @@ impl Session { self.diagnostic().span_err_with_code(sp, msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.diagnostic().err(msg) } @@ -583,12 +586,16 @@ impl Session { )) } } + + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] #[track_caller] pub fn span_warn>(&self, sp: S, msg: impl Into) { self.diagnostic().span_warn(sp, msg) } + + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn_with_code>( @@ -599,6 +606,10 @@ impl Session { ) { self.diagnostic().span_warn_with_code(sp, msg, code) } + + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn warn(&self, msg: impl Into) { self.diagnostic().warn(msg) } @@ -641,11 +652,17 @@ impl Session { self.diagnostic().delay_good_path_bug(msg) } + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn note_without_error(&self, msg: impl Into) { self.diagnostic().note_without_error(msg) } #[track_caller] + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_note_without_error>( &self, sp: S, @@ -653,6 +670,8 @@ impl Session { ) { self.diagnostic().span_note_without_error(sp, msg) } + + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_note_without_error( @@ -882,7 +901,7 @@ impl Session { // We only call `msg` in case we can actually emit warnings. // Otherwise, this could cause a `delay_good_path_bug` to // trigger (issue #79546). - self.warn(&format!("optimization-fuel-exhausted: {}", msg())); + self.emit_warning(OptimisationFuelExhausted { msg: msg() }); } fuel.out_of_fuel = true; } else if fuel.remaining > 0 { diff --git a/tests/run-make/incremental-session-fail/Makefile b/tests/run-make/incremental-session-fail/Makefile index 0461bb926e76e..6ce1370927bc1 100644 --- a/tests/run-make/incremental-session-fail/Makefile +++ b/tests/run-make/incremental-session-fail/Makefile @@ -9,6 +9,6 @@ all: touch $(SESSION_DIR) # Check exit code is 1 for an error, and not 101 for ICE. $(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ] - $(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE) + $(CGREP) "could not create incremental compilation crate directory" < $(OUTPUT_FILE) # -v tests are fragile, hopefully this text won't change $(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)