Auto merge of #100754 - davidtwco:translation-incremental, r=compiler-errors

incremental: migrate diagnostics

- Apply the diagnostic migration lints to more functions on `Session`, namely: `span_warn`, `span_warn_with_code`, `warn` `note_without_error`, `span_note_without_error`, `struct_note_without_error`.
- Add impls of `IntoDiagnosticArg` for `std::io::Error`, `std::path::Path` and `std::path::PathBuf`.
- Migrate the `rustc_incremental` crate's diagnostics to translatable diagnostic structs.

r? `@compiler-errors`
cc #100717
This commit is contained in:
bors 2023-01-31 10:20:58 +00:00
commit a64ef7d07d
49 changed files with 1158 additions and 429 deletions

View file

@ -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()

View file

@ -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>,

View file

@ -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)]

View file

@ -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;

View file

@ -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))
}
}

View file

@ -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 {

View file

@ -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<EM: EmissionGuarantee> 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<EM: EmissionGuarantee> 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,
}

View file

@ -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(hash_raw_entry)]
#![feature(let_chains)]
#![feature(extern_types)]
#![feature(once_cell)]
#![feature(hash_raw_entry)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(once_cell)]
#![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)));
}
};

View file

@ -305,8 +305,12 @@ impl TargetMachineFactoryConfig {
}
pub type TargetMachineFactoryFn<B> = Arc<
dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String>
+ Send
dyn Fn(
TargetMachineFactoryConfig,
) -> Result<
<B as WriteBackendMethods>::TargetMachine,
<B as WriteBackendMethods>::TargetMachineError,
> + Send
+ Sync,
>;

View file

@ -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;

View file

@ -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<Cow<'static, str>> = 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");

View file

@ -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;

View file

@ -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}

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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",

View file

@ -1051,6 +1051,7 @@ impl Diagnostic {
) -> (
&Level,
&[(DiagnosticMessage, Style)],
Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
&Option<DiagnosticId>,
&MultiSpan,
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@ -1059,6 +1060,7 @@ impl Diagnostic {
(
&self.level,
&self.message,
self.args().collect(),
&self.code,
&self.span,
&self.suggestions,

View file

@ -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<DiagnosticMessage>,
) -> 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<DiagnosticMessage>,
) -> 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

View file

@ -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()))

View file

@ -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<Item = DiagnosticArg<'a, 'static>>,
) -> 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<Item = DiagnosticArg<'a, 'static>>,
) -> 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<MultiSpan>,
@ -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<DiagnosticMessage>) -> FatalError {
self.inner.borrow_mut().fatal(msg)
}
#[rustc_lint_diagnostics]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.inner.borrow_mut().err(msg)
}
#[rustc_lint_diagnostics]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
let mut db = DiagnosticBuilder::new(self, Warning(None), msg);
db.emit();
}
#[rustc_lint_diagnostics]
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
DiagnosticBuilder::new(self, Note, msg).emit();
}
@ -1059,6 +1067,7 @@ impl Handler {
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
}
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
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,

View file

@ -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);
}

View file

@ -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,
}

View file

@ -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 });
}
}
}

View file

@ -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

View file

@ -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,
}

View file

@ -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;

View file

@ -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<A> 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<ast::AttrId>) {
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);
}
}

View file

@ -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 });
}
}
}

View file

@ -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));
}

View file

@ -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<T> {
},
/// 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<dyn std::any::Any + Send>),
}
impl<T: Default> LoadResult<T> {
@ -40,36 +40,31 @@ impl<T: Default> LoadResult<T> {
// 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<T> MaybeAsync<LoadResult<T>> {
pub fn open(self) -> LoadResult<T> {
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);

View file

@ -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;
}
};

View file

@ -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 });
}
}
}

View file

@ -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']

View file

@ -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;

View file

@ -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<C
}
base.retain(|crate_type| {
let res = !output::invalid_output_for_target(session, *crate_type);
if !res {
session.warn(&format!(
"dropping unsupported crate type `{}` for target `{}`",
*crate_type, session.opts.target_triple
));
if output::invalid_output_for_target(session, *crate_type) {
session.emit_warning(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
});
false
} else {
true
}
res
});
base
@ -517,19 +517,16 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> 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(

View file

@ -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);

View file

@ -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,
}

View file

@ -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

View file

@ -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;
}

View file

@ -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,
}

View file

@ -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`

View file

@ -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,
}

View file

@ -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<DiagnosticMessage>) -> 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<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
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<S: Into<MultiSpan>>(
@ -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<DiagnosticMessage>) {
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<DiagnosticMessage>) {
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<S: Into<MultiSpan>>(
&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 {

View file

@ -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)