Skip to content

Commit 753afae

Browse files
committed
Move IntoDiagArg earlier in the dependency chains
`rustc_errors` depends on numerous crates, solely to implement its `IntoDiagArg` trait on types from those crates. Many crates depend on `rustc_errors`, and it's on the critical path. We can't swap things around to make all of those crates depend on `rustc_errors` instead, because `rustc_errors` would end up in dependency cycles. Instead, move `IntoDiagArg` into `rustc_error_messages`, which has far fewer dependencies, and then have most of these crates depend on `rustc_error_messages`. This allows `rustc_errors` to drop dependencies on several crates, including the large `rustc_target`. (This doesn't fully reduce dependency chains yet, as `rustc_errors` still depends on `rustc_hir` which depends on `rustc_target`. That will get fixed in a subsequent commit.)
1 parent 2c1ac85 commit 753afae

File tree

22 files changed

+431
-408
lines changed

22 files changed

+431
-408
lines changed

Cargo.lock

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,6 +3367,7 @@ dependencies = [
33673367
"rand 0.9.2",
33683368
"rand_xoshiro",
33693369
"rustc_data_structures",
3370+
"rustc_error_messages",
33703371
"rustc_hashes",
33713372
"rustc_index",
33723373
"rustc_macros",
@@ -3777,6 +3778,8 @@ dependencies = [
37773778
"icu_locid",
37783779
"icu_provider_adapters",
37793780
"intl-memoizer",
3781+
"rustc_ast",
3782+
"rustc_ast_pretty",
37803783
"rustc_baked_icu_data",
37813784
"rustc_data_structures",
37823785
"rustc_macros",
@@ -3793,8 +3796,6 @@ dependencies = [
37933796
"annotate-snippets 0.11.5",
37943797
"derive_setters",
37953798
"rustc_abi",
3796-
"rustc_ast",
3797-
"rustc_ast_pretty",
37983799
"rustc_data_structures",
37993800
"rustc_error_codes",
38003801
"rustc_error_messages",
@@ -3807,8 +3808,6 @@ dependencies = [
38073808
"rustc_macros",
38083809
"rustc_serialize",
38093810
"rustc_span",
3810-
"rustc_target",
3811-
"rustc_type_ir",
38123811
"serde",
38133812
"serde_json",
38143813
"termcolor",
@@ -3896,6 +3895,7 @@ dependencies = [
38963895
"rustc_ast",
38973896
"rustc_ast_pretty",
38983897
"rustc_data_structures",
3898+
"rustc_error_messages",
38993899
"rustc_hashes",
39003900
"rustc_index",
39013901
"rustc_macros",
@@ -4647,6 +4647,7 @@ dependencies = [
46474647
"object 0.37.2",
46484648
"rustc_abi",
46494649
"rustc_data_structures",
4650+
"rustc_error_messages",
46504651
"rustc_fs_util",
46514652
"rustc_macros",
46524653
"rustc_serialize",
@@ -4765,6 +4766,7 @@ dependencies = [
47654766
"rustc-hash 2.1.1",
47664767
"rustc_ast_ir",
47674768
"rustc_data_structures",
4769+
"rustc_error_messages",
47684770
"rustc_index",
47694771
"rustc_macros",
47704772
"rustc_serialize",

compiler/rustc_abi/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ bitflags = "2.4.1"
99
rand = { version = "0.9.0", default-features = false, optional = true }
1010
rand_xoshiro = { version = "0.7.0", optional = true }
1111
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
12+
rustc_error_messages = { path = "../rustc_error_messages", optional = true }
1213
rustc_hashes = { path = "../rustc_hashes" }
1314
rustc_index = { path = "../rustc_index", default-features = false }
1415
rustc_macros = { path = "../rustc_macros", optional = true }
@@ -24,6 +25,7 @@ default = ["nightly", "randomize"]
2425
# without depending on rustc_data_structures, rustc_macros and rustc_serialize
2526
nightly = [
2627
"dep:rustc_data_structures",
28+
"dep:rustc_error_messages",
2729
"dep:rustc_macros",
2830
"dep:rustc_serialize",
2931
"dep:rustc_span",

compiler/rustc_abi/src/extern_abi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ impl StableOrd for ExternAbi {
223223
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
224224
}
225225

226+
#[cfg(feature = "nightly")]
227+
rustc_error_messages::into_diag_arg_using_display!(ExternAbi);
228+
226229
impl ExternAbi {
227230
/// An ABI "like Rust"
228231
///

compiler/rustc_error_messages/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ icu_list = "1.2"
1111
icu_locid = "1.2"
1212
icu_provider_adapters = "1.2"
1313
intl-memoizer = "0.5.1"
14+
rustc_ast = { path = "../rustc_ast" }
15+
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
1416
rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
1517
rustc_data_structures = { path = "../rustc_data_structures" }
1618
rustc_macros = { path = "../rustc_macros" }
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
use std::backtrace::Backtrace;
2+
use std::borrow::Cow;
3+
use std::fmt;
4+
use std::num::ParseIntError;
5+
use std::path::{Path, PathBuf};
6+
use std::process::ExitStatus;
7+
8+
use rustc_ast as ast;
9+
use rustc_ast_pretty::pprust;
10+
use rustc_span::edition::Edition;
11+
12+
use crate::{DiagArgValue, IntoDiagArg};
13+
14+
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
15+
16+
impl IntoDiagArg for DiagArgFromDisplay<'_> {
17+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
18+
self.0.to_string().into_diag_arg(path)
19+
}
20+
}
21+
22+
impl<'a> From<&'a dyn fmt::Display> for DiagArgFromDisplay<'a> {
23+
fn from(t: &'a dyn fmt::Display) -> Self {
24+
DiagArgFromDisplay(t)
25+
}
26+
}
27+
28+
impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
29+
fn from(t: &'a T) -> Self {
30+
DiagArgFromDisplay(t)
31+
}
32+
}
33+
34+
impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
35+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
36+
self.clone().into_diag_arg(path)
37+
}
38+
}
39+
40+
#[macro_export]
41+
macro_rules! into_diag_arg_using_display {
42+
($( $ty:ty ),+ $(,)?) => {
43+
$(
44+
impl $crate::IntoDiagArg for $ty {
45+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
46+
self.to_string().into_diag_arg(path)
47+
}
48+
}
49+
)+
50+
}
51+
}
52+
53+
macro_rules! into_diag_arg_for_number {
54+
($( $ty:ty ),+ $(,)?) => {
55+
$(
56+
impl $crate::IntoDiagArg for $ty {
57+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
58+
// Convert to a string if it won't fit into `Number`.
59+
#[allow(irrefutable_let_patterns)]
60+
if let Ok(n) = TryInto::<i32>::try_into(self) {
61+
$crate::DiagArgValue::Number(n)
62+
} else {
63+
self.to_string().into_diag_arg(path)
64+
}
65+
}
66+
}
67+
)+
68+
}
69+
}
70+
71+
into_diag_arg_using_display!(
72+
ast::ParamKindOrd,
73+
std::io::Error,
74+
Box<dyn std::error::Error>,
75+
std::num::NonZero<u32>,
76+
Edition,
77+
rustc_span::Ident,
78+
rustc_span::MacroRulesNormalizedIdent,
79+
ParseIntError,
80+
ExitStatus,
81+
);
82+
83+
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
84+
85+
impl IntoDiagArg for bool {
86+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
87+
if self {
88+
DiagArgValue::Str(Cow::Borrowed("true"))
89+
} else {
90+
DiagArgValue::Str(Cow::Borrowed("false"))
91+
}
92+
}
93+
}
94+
95+
impl IntoDiagArg for char {
96+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
97+
DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
98+
}
99+
}
100+
101+
impl IntoDiagArg for Vec<char> {
102+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
103+
DiagArgValue::StrListSepByAnd(
104+
self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
105+
)
106+
}
107+
}
108+
109+
impl IntoDiagArg for rustc_span::Symbol {
110+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
111+
self.to_ident_string().into_diag_arg(path)
112+
}
113+
}
114+
115+
impl<'a> IntoDiagArg for &'a str {
116+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
117+
self.to_string().into_diag_arg(path)
118+
}
119+
}
120+
121+
impl IntoDiagArg for String {
122+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
123+
DiagArgValue::Str(Cow::Owned(self))
124+
}
125+
}
126+
127+
impl<'a> IntoDiagArg for Cow<'a, str> {
128+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
129+
DiagArgValue::Str(Cow::Owned(self.into_owned()))
130+
}
131+
}
132+
133+
impl<'a> IntoDiagArg for &'a Path {
134+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
135+
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
136+
}
137+
}
138+
139+
impl IntoDiagArg for PathBuf {
140+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
141+
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
142+
}
143+
}
144+
145+
impl IntoDiagArg for ast::Expr {
146+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
147+
DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
148+
}
149+
}
150+
151+
impl IntoDiagArg for ast::Path {
152+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
153+
DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
154+
}
155+
}
156+
157+
impl IntoDiagArg for ast::token::Token {
158+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
159+
DiagArgValue::Str(pprust::token_to_string(&self))
160+
}
161+
}
162+
163+
impl IntoDiagArg for ast::token::TokenKind {
164+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
165+
DiagArgValue::Str(pprust::token_kind_to_string(&self))
166+
}
167+
}
168+
169+
impl IntoDiagArg for std::ffi::CString {
170+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
171+
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
172+
}
173+
}
174+
175+
impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
176+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
177+
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
178+
}
179+
}
180+
181+
impl IntoDiagArg for ast::Visibility {
182+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
183+
let s = pprust::vis_to_string(&self);
184+
let s = s.trim_end().to_string();
185+
DiagArgValue::Str(Cow::Owned(s))
186+
}
187+
}
188+
189+
impl IntoDiagArg for Backtrace {
190+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
191+
DiagArgValue::Str(Cow::from(self.to_string()))
192+
}
193+
}
194+
195+
impl IntoDiagArg for ast::util::parser::ExprPrecedence {
196+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
197+
DiagArgValue::Number(self as i32)
198+
}
199+
}
200+
201+
impl IntoDiagArg for ast::FloatTy {
202+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
203+
DiagArgValue::Str(Cow::Borrowed(self.name_str()))
204+
}
205+
}

compiler/rustc_error_messages/src/lib.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ use rustc_span::Span;
2323
use tracing::{instrument, trace};
2424
pub use unic_langid::{LanguageIdentifier, langid};
2525

26+
mod diagnostic_impls;
27+
pub use diagnostic_impls::DiagArgFromDisplay;
28+
2629
pub type FluentBundle =
2730
IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
2831

@@ -589,3 +592,53 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu
589592

590593
FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
591594
}
595+
596+
/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
597+
/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
598+
/// emission.
599+
pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
600+
601+
/// Name of a diagnostic argument.
602+
pub type DiagArgName = Cow<'static, str>;
603+
604+
/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
605+
/// to a `FluentValue` by the emitter to be used in diagnostic translation.
606+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
607+
pub enum DiagArgValue {
608+
Str(Cow<'static, str>),
609+
// This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
610+
// safely fits in an `f64`. Any integers bigger than that will be converted
611+
// to strings in `into_diag_arg` and stored using the `Str` variant.
612+
Number(i32),
613+
StrListSepByAnd(Vec<Cow<'static, str>>),
614+
}
615+
616+
/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
617+
/// Implemented as a custom trait rather than `From` so that it is implemented on the type being
618+
/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
619+
/// implement this.
620+
pub trait IntoDiagArg {
621+
/// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
622+
///
623+
/// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
624+
/// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
625+
/// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
626+
/// value has no shortening logic that could be used, the argument can be safely ignored.
627+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
628+
}
629+
630+
impl IntoDiagArg for DiagArgValue {
631+
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
632+
self
633+
}
634+
}
635+
636+
impl From<DiagArgValue> for FluentValue<'static> {
637+
fn from(val: DiagArgValue) -> Self {
638+
match val {
639+
DiagArgValue::Str(s) => From::from(s),
640+
DiagArgValue::Number(n) => From::from(n),
641+
DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
642+
}
643+
}
644+
}

compiler/rustc_errors/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ edition = "2024"
88
annotate-snippets = "0.11"
99
derive_setters = "0.1.6"
1010
rustc_abi = { path = "../rustc_abi" }
11-
rustc_ast = { path = "../rustc_ast" }
12-
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
1311
rustc_data_structures = { path = "../rustc_data_structures" }
1412
rustc_error_codes = { path = "../rustc_error_codes" }
1513
rustc_error_messages = { path = "../rustc_error_messages" }
@@ -22,8 +20,6 @@ rustc_lint_defs = { path = "../rustc_lint_defs" }
2220
rustc_macros = { path = "../rustc_macros" }
2321
rustc_serialize = { path = "../rustc_serialize" }
2422
rustc_span = { path = "../rustc_span" }
25-
rustc_target = { path = "../rustc_target" }
26-
rustc_type_ir = { path = "../rustc_type_ir" }
2723
serde = { version = "1.0.125", features = ["derive"] }
2824
serde_json = "1.0.59"
2925
termcolor = "1.2.0"

compiler/rustc_errors/src/codes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ impl fmt::Display for ErrCode {
2020
}
2121
}
2222

23+
rustc_error_messages::into_diag_arg_using_display!(ErrCode);
24+
2325
macro_rules! define_error_code_constants_and_diagnostics_table {
2426
($($name:ident: $num:literal,)*) => (
2527
$(

0 commit comments

Comments
 (0)