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) -> 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) -> 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) -> $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) -> $crate::DiagArgValue { // Convert to a string if it won't fit into `Number`. #[allow(irrefutable_let_patterns)] if let Ok(n) = TryInto::::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, std::num::NonZero, 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) -> 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) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) } } impl IntoDiagArg for Vec { fn into_diag_arg(self, _: &mut Option) -> 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) -> DiagArgValue { self.to_ident_string().into_diag_arg(path) } } impl<'a> IntoDiagArg for &'a str { fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { self.to_string().into_diag_arg(path) } } impl IntoDiagArg for String { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self)) } } impl<'a> IntoDiagArg for Cow<'a, str> { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.into_owned())) } } impl<'a> IntoDiagArg for &'a Path { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagArg for PathBuf { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagArg for ast::Expr { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self))) } } impl IntoDiagArg for ast::Path { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) } } impl IntoDiagArg for ast::token::Token { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(pprust::token_to_string(&self)) } } impl IntoDiagArg for ast::token::TokenKind { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(pprust::token_kind_to_string(&self)) } } impl IntoDiagArg for std::ffi::CString { fn into_diag_arg(self, _: &mut Option) -> 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) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) } } impl IntoDiagArg for ast::Visibility { fn into_diag_arg(self, _: &mut Option) -> 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) -> DiagArgValue { DiagArgValue::Str(Cow::from(self.to_string())) } } impl IntoDiagArg for ast::util::parser::ExprPrecedence { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Number(self as i32) } } impl IntoDiagArg for ast::FloatTy { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.name_str())) } }