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.)
This commit is contained in:
parent
040a98af70
commit
b65fab6299
23 changed files with 425 additions and 395 deletions
|
|
@ -11,6 +11,8 @@ icu_list = "1.2"
|
|||
icu_locid = "1.2"
|
||||
icu_provider_adapters = "1.2"
|
||||
intl-memoizer = "0.5.1"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
|
|
|
|||
205
compiler/rustc_error_messages/src/diagnostic_impls.rs
Normal file
205
compiler/rustc_error_messages/src/diagnostic_impls.rs
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
use std::backtrace::Backtrace;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitStatus;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_span::edition::Edition;
|
||||
|
||||
use crate::{DiagArgValue, IntoDiagArg};
|
||||
|
||||
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
|
||||
|
||||
impl IntoDiagArg for DiagArgFromDisplay<'_> {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.0.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a dyn fmt::Display> for DiagArgFromDisplay<'a> {
|
||||
fn from(t: &'a dyn fmt::Display) -> Self {
|
||||
DiagArgFromDisplay(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
|
||||
fn from(t: &'a T) -> Self {
|
||||
DiagArgFromDisplay(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.clone().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! into_diag_arg_using_display {
|
||||
($( $ty:ty ),+ $(,)?) => {
|
||||
$(
|
||||
impl $crate::IntoDiagArg for $ty {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! into_diag_arg_for_number {
|
||||
($( $ty:ty ),+ $(,)?) => {
|
||||
$(
|
||||
impl $crate::IntoDiagArg for $ty {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
|
||||
// Convert to a string if it won't fit into `Number`.
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Ok(n) = TryInto::<i32>::try_into(self) {
|
||||
$crate::DiagArgValue::Number(n)
|
||||
} else {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
into_diag_arg_using_display!(
|
||||
ast::ParamKindOrd,
|
||||
std::io::Error,
|
||||
Box<dyn std::error::Error>,
|
||||
std::num::NonZero<u32>,
|
||||
Edition,
|
||||
rustc_span::Ident,
|
||||
rustc_span::MacroRulesNormalizedIdent,
|
||||
ParseIntError,
|
||||
ExitStatus,
|
||||
);
|
||||
|
||||
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||
|
||||
impl IntoDiagArg for bool {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
if self {
|
||||
DiagArgValue::Str(Cow::Borrowed("true"))
|
||||
} else {
|
||||
DiagArgValue::Str(Cow::Borrowed("false"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for char {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Vec<char> {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::StrListSepByAnd(
|
||||
self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for rustc_span::Symbol {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_ident_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for &'a str {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for String {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for Cow<'a, str> {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for &'a Path {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for PathBuf {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::Expr {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::Path {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::token::Token {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(pprust::token_to_string(&self))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::token::TokenKind {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(pprust::token_kind_to_string(&self))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for std::ffi::CString {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::Visibility {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
let s = pprust::vis_to_string(&self);
|
||||
let s = s.trim_end().to_string();
|
||||
DiagArgValue::Str(Cow::Owned(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Backtrace {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::util::parser::ExprPrecedence {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Number(self as i32)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::FloatTy {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.name_str()))
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,9 @@ use rustc_span::Span;
|
|||
use tracing::{instrument, trace};
|
||||
pub use unic_langid::{LanguageIdentifier, langid};
|
||||
|
||||
mod diagnostic_impls;
|
||||
pub use diagnostic_impls::DiagArgFromDisplay;
|
||||
|
||||
pub type FluentBundle =
|
||||
IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
|
||||
|
||||
|
|
@ -589,3 +592,53 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu
|
|||
|
||||
FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
|
||||
}
|
||||
|
||||
/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
|
||||
/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
|
||||
/// emission.
|
||||
pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
|
||||
|
||||
/// Name of a diagnostic argument.
|
||||
pub type DiagArgName = Cow<'static, str>;
|
||||
|
||||
/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
|
||||
/// to a `FluentValue` by the emitter to be used in diagnostic translation.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum DiagArgValue {
|
||||
Str(Cow<'static, str>),
|
||||
// This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
|
||||
// safely fits in an `f64`. Any integers bigger than that will be converted
|
||||
// to strings in `into_diag_arg` and stored using the `Str` variant.
|
||||
Number(i32),
|
||||
StrListSepByAnd(Vec<Cow<'static, str>>),
|
||||
}
|
||||
|
||||
/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
|
||||
/// Implemented as a custom trait rather than `From` so that it is implemented on the type being
|
||||
/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
|
||||
/// implement this.
|
||||
pub trait IntoDiagArg {
|
||||
/// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
|
||||
///
|
||||
/// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
|
||||
/// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
|
||||
/// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
|
||||
/// value has no shortening logic that could be used, the argument can be safely ignored.
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
|
||||
}
|
||||
|
||||
impl IntoDiagArg for DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DiagArgValue> for FluentValue<'static> {
|
||||
fn from(val: DiagArgValue) -> Self {
|
||||
match val {
|
||||
DiagArgValue::Str(s) => From::from(s),
|
||||
DiagArgValue::Number(n) => From::from(n),
|
||||
DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue