Rollup merge of #154449 - nnethercote:rustc_errors-dep-rustc_abi, r=davidtwco

Invert dependency between `rustc_errors` and `rustc_abi`.

Currently, `rustc_errors` depends on `rustc_abi`, which depends on `rustc_error_messages`. This is a bit odd.

`rustc_errors` depends on `rustc_abi` for a single reason: `rustc_abi` defines a type `TargetDataLayoutErrors` and `rustc_errors` impls `Diagnostic` for that type.

We can get a more natural relationship by inverting the dependency, moving the `Diagnostic` trait upstream. Then `rustc_abi` defines `TargetDataLayoutErrors` and also impls `Diagnostic` for it. `rustc_errors` is already pretty far upstream in the crate graph, it doesn't hurt to push it a little further because errors are a very low-level concept.

r? @davidtwco
This commit is contained in:
Jonathan Brouwer
2026-04-10 18:38:13 +02:00
committed by GitHub
8 changed files with 79 additions and 83 deletions
+1 -1
View File
@@ -3505,6 +3505,7 @@ dependencies = [
"rand_xoshiro",
"rustc_data_structures",
"rustc_error_messages",
"rustc_errors",
"rustc_hashes",
"rustc_index",
"rustc_macros",
@@ -3909,7 +3910,6 @@ dependencies = [
"anstream",
"anstyle",
"derive_setters",
"rustc_abi",
"rustc_ast",
"rustc_data_structures",
"rustc_error_codes",
+4 -2
View File
@@ -10,6 +10,7 @@ rand = { version = "0.9.0", default-features = false, optional = true }
rand_xoshiro = { version = "0.7.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_error_messages = { path = "../rustc_error_messages", optional = true }
rustc_errors = { path = "../rustc_errors", optional = true }
rustc_hashes = { path = "../rustc_hashes" }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
@@ -21,11 +22,12 @@ tracing = "0.1"
[features]
# tidy-alphabetical-start
default = ["nightly", "randomize"]
# rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
# without depending on rustc_data_structures, rustc_macros and rustc_serialize
# rust-analyzer depends on this crate and we therefore require it to build on a stable toolchain
# without depending on the rustc_* crates in the following list.
nightly = [
"dep:rustc_data_structures",
"dep:rustc_error_messages",
"dep:rustc_errors",
"dep:rustc_macros",
"dep:rustc_serialize",
"dep:rustc_span",
+55 -8
View File
@@ -46,6 +46,8 @@
use bitflags::bitflags;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
#[cfg(feature = "nightly")]
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg};
use rustc_hashes::Hash64;
use rustc_index::{Idx, IndexSlice, IndexVec};
#[cfg(feature = "nightly")]
@@ -332,7 +334,7 @@ fn default() -> TargetDataLayout {
}
}
pub enum TargetDataLayoutErrors<'a> {
pub enum TargetDataLayoutError<'a> {
InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
MissingAlignment { cause: &'a str },
@@ -343,6 +345,51 @@ pub enum TargetDataLayoutErrors<'a> {
UnknownPointerSpecification { err: String },
}
#[cfg(feature = "nightly")]
impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutError<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
match self {
TargetDataLayoutError::InvalidAddressSpace { addr_space, err, cause } => {
Diag::new(dcx, level, msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}"))
.with_arg("addr_space", addr_space)
.with_arg("cause", cause)
.with_arg("err", err)
}
TargetDataLayoutError::InvalidBits { kind, bit, cause, err } => {
Diag::new(dcx, level, msg!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}"))
.with_arg("kind", kind)
.with_arg("bit", bit)
.with_arg("cause", cause)
.with_arg("err", err)
}
TargetDataLayoutError::MissingAlignment { cause } => {
Diag::new(dcx, level, msg!("missing alignment for `{$cause}` in \"data-layout\""))
.with_arg("cause", cause)
}
TargetDataLayoutError::InvalidAlignment { cause, err } => {
Diag::new(dcx, level, msg!("invalid alignment for `{$cause}` in \"data-layout\": {$err}"))
.with_arg("cause", cause)
.with_arg("err", err.to_string())
}
TargetDataLayoutError::InconsistentTargetArchitecture { dl, target } => {
Diag::new(dcx, level, msg!("inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`"))
.with_arg("dl", dl).with_arg("target", target)
}
TargetDataLayoutError::InconsistentTargetPointerWidth { pointer_size, target } => {
Diag::new(dcx, level, msg!("inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`"))
.with_arg("pointer_size", pointer_size).with_arg("target", target)
}
TargetDataLayoutError::InvalidBitsSize { err } => {
Diag::new(dcx, level, msg!("{$err}")).with_arg("err", err)
}
TargetDataLayoutError::UnknownPointerSpecification { err } => {
Diag::new(dcx, level, msg!("unknown pointer specification `{$err}` in datalayout string"))
.with_arg("err", err)
}
}
}
}
impl TargetDataLayout {
/// Parse data layout from an
/// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
@@ -352,17 +399,17 @@ impl TargetDataLayout {
pub fn parse_from_llvm_datalayout_string<'a>(
input: &'a str,
default_address_space: AddressSpace,
) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
) -> Result<TargetDataLayout, TargetDataLayoutError<'a>> {
// Parse an address space index from a string.
let parse_address_space = |s: &'a str, cause: &'a str| {
s.parse::<u32>().map(AddressSpace).map_err(|err| {
TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
TargetDataLayoutError::InvalidAddressSpace { addr_space: s, cause, err }
})
};
// Parse a bit count from a string.
let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
s.parse::<u64>().map_err(|err| TargetDataLayoutError::InvalidBits {
kind,
bit: s,
cause,
@@ -378,7 +425,7 @@ pub fn parse_from_llvm_datalayout_string<'a>(
let parse_align_str = |s: &'a str, cause: &'a str| {
let align_from_bits = |bits| {
Align::from_bits(bits)
.map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
.map_err(|err| TargetDataLayoutError::InvalidAlignment { cause, err })
};
let abi = parse_bits(s, "alignment", cause)?;
Ok(align_from_bits(abi)?)
@@ -388,7 +435,7 @@ pub fn parse_from_llvm_datalayout_string<'a>(
// ignoring the secondary alignment specifications.
let parse_align_seq = |s: &[&'a str], cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
return Err(TargetDataLayoutError::MissingAlignment { cause });
}
parse_align_str(s[0], cause)
};
@@ -426,7 +473,7 @@ pub fn parse_from_llvm_datalayout_string<'a>(
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
return Err(TargetDataLayoutError::UnknownPointerSpecification {
err: p.to_string(),
});
}
@@ -471,7 +518,7 @@ pub fn parse_from_llvm_datalayout_string<'a>(
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
return Err(TargetDataLayoutError::UnknownPointerSpecification {
err: p.to_string(),
});
}
+7 -7
View File
@@ -256,7 +256,7 @@ pub struct CompiledModules {
pub allocator_module: Option<CompiledModule>,
}
pub enum CodegenErrors {
pub enum CodegenError {
WrongFileType,
EmptyVersionNumber,
EncodingVersionMismatch { version_array: String, rlink_version: u32 },
@@ -317,32 +317,32 @@ pub fn serialize_rlink(
pub fn deserialize_rlink(
sess: &Session,
data: Vec<u8>,
) -> Result<(Self, CrateInfo, EncodedMetadata, OutputFilenames), CodegenErrors> {
) -> Result<(Self, CrateInfo, EncodedMetadata, OutputFilenames), CodegenError> {
// The Decodable machinery is not used here because it panics if the input data is invalid
// and because its internal representation may change.
if !data.starts_with(RLINK_MAGIC) {
return Err(CodegenErrors::WrongFileType);
return Err(CodegenError::WrongFileType);
}
let data = &data[RLINK_MAGIC.len()..];
if data.len() < 4 {
return Err(CodegenErrors::EmptyVersionNumber);
return Err(CodegenError::EmptyVersionNumber);
}
let mut version_array: [u8; 4] = Default::default();
version_array.copy_from_slice(&data[..4]);
if u32::from_be_bytes(version_array) != RLINK_VERSION {
return Err(CodegenErrors::EncodingVersionMismatch {
return Err(CodegenError::EncodingVersionMismatch {
version_array: String::from_utf8_lossy(&version_array).to_string(),
rlink_version: RLINK_VERSION,
});
}
let Ok(mut decoder) = MemDecoder::new(&data[4..], 0) else {
return Err(CodegenErrors::CorruptFile);
return Err(CodegenError::CorruptFile);
};
let rustc_version = decoder.read_str();
if rustc_version != sess.cfg_version {
return Err(CodegenErrors::RustcVersionMismatch {
return Err(CodegenError::RustcVersionMismatch {
rustc_version: rustc_version.to_string(),
});
}
+6 -8
View File
@@ -28,7 +28,7 @@
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenErrors, CompiledModules};
use rustc_codegen_ssa::{CodegenError, CompiledModules};
use rustc_data_structures::profiling::{
TimePassesFormat, get_resident_set_size, print_time_passes_entry,
};
@@ -567,23 +567,21 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
}
Err(err) => {
match err {
CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => {
dcx.emit_fatal(RLinkEmptyVersionNumber)
}
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
CodegenError::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenError::EmptyVersionNumber => dcx.emit_fatal(RLinkEmptyVersionNumber),
CodegenError::EncodingVersionMismatch { version_array, rlink_version } => {
dcx.emit_fatal(RLinkEncodingVersionMismatch {
version_array,
rlink_version,
})
}
CodegenErrors::RustcVersionMismatch { rustc_version } => {
CodegenError::RustcVersionMismatch { rustc_version } => {
dcx.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version: sess.cfg_version,
})
}
CodegenErrors::CorruptFile => {
CodegenError::CorruptFile => {
dcx.emit_fatal(RlinkCorruptFile { file });
}
};
-1
View File
@@ -9,7 +9,6 @@ annotate-snippets = { version = "0.12.15", features = ["simd"] }
anstream = "0.6.20"
anstyle = "1.0.13"
derive_setters = "0.1.6"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_error_codes = { path = "../rustc_error_codes" }
+1 -51
View File
@@ -1,12 +1,11 @@
use std::borrow::Cow;
use rustc_abi::TargetDataLayoutErrors;
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
use rustc_macros::Subdiagnostic;
use rustc_span::{Span, Symbol};
use crate::diagnostic::DiagLocation;
use crate::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, msg};
use crate::{Diag, EmissionGuarantee, Subdiagnostic};
impl IntoDiagArg for DiagLocation {
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
@@ -37,55 +36,6 @@ fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
}
}
impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
match self {
TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
Diag::new(dcx, level, msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}"))
.with_arg("addr_space", addr_space)
.with_arg("cause", cause)
.with_arg("err", err)
}
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
Diag::new(dcx, level, msg!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}"))
.with_arg("kind", kind)
.with_arg("bit", bit)
.with_arg("cause", cause)
.with_arg("err", err)
}
TargetDataLayoutErrors::MissingAlignment { cause } => {
Diag::new(dcx, level, msg!("missing alignment for `{$cause}` in \"data-layout\""))
.with_arg("cause", cause)
}
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
Diag::new(dcx, level, msg!(
"invalid alignment for `{$cause}` in \"data-layout\": {$err}"
))
.with_arg("cause", cause)
.with_arg("err", err.to_string())
}
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
Diag::new(dcx, level, msg!(
"inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`"
))
.with_arg("dl", dl).with_arg("target", target)
}
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
Diag::new(dcx, level, msg!(
"inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`"
)).with_arg("pointer_size", pointer_size).with_arg("target", target)
}
TargetDataLayoutErrors::InvalidBitsSize { err } => {
Diag::new(dcx, level, msg!("{$err}")).with_arg("err", err)
}
TargetDataLayoutErrors::UnknownPointerSpecification { err } => {
Diag::new(dcx, level, msg!("unknown pointer specification `{$err}` in datalayout string"))
.with_arg("err", err)
}
}
}
}
/// Utility struct used to apply a single label while highlighting multiple spans
pub struct SingleLabelManySpans {
pub spans: Vec<Span>,
+5 -5
View File
@@ -47,7 +47,7 @@
use std::{fmt, io};
use rustc_abi::{
Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutError,
};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_error_messages::{DiagArgValue, IntoDiagArg, into_diag_arg_using_display};
@@ -2166,7 +2166,7 @@ pub struct TargetMetadata {
}
impl Target {
pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutError<'_>> {
let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
&self.data_layout,
self.options.default_address_space,
@@ -2174,7 +2174,7 @@ pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErro
// Perform consistency checks against the Target information.
if dl.endian != self.endian {
return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
return Err(TargetDataLayoutError::InconsistentTargetArchitecture {
dl: dl.endian.as_str(),
target: self.endian.as_str(),
});
@@ -2183,7 +2183,7 @@ pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErro
let target_pointer_width: u64 = self.pointer_width.into();
let dl_pointer_size: u64 = dl.pointer_size().bits();
if dl_pointer_size != target_pointer_width {
return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
return Err(TargetDataLayoutError::InconsistentTargetPointerWidth {
pointer_size: dl_pointer_size,
target: self.pointer_width,
});
@@ -2192,7 +2192,7 @@ pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErro
dl.c_enum_min_size = Integer::from_size(Size::from_bits(
self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
))
.map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
.map_err(|err| TargetDataLayoutError::InvalidBitsSize { err })?;
Ok(dl)
}