]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_errors/src/diagnostic_impls.rs
Rollup merge of #104233 - compiler-errors:issue-104209, r=lcnr
[rust.git] / compiler / rustc_errors / src / diagnostic_impls.rs
1 use crate::{
2     fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
3 };
4 use rustc_ast as ast;
5 use rustc_ast_pretty::pprust;
6 use rustc_hir as hir;
7 use rustc_lint_defs::Level;
8 use rustc_span::edition::Edition;
9 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
10 use rustc_target::abi::TargetDataLayoutErrors;
11 use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
12 use std::borrow::Cow;
13 use std::fmt;
14 use std::fmt::Write;
15 use std::num::ParseIntError;
16 use std::path::{Path, PathBuf};
17 use std::process::ExitStatus;
18
19 pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display);
20
21 impl IntoDiagnosticArg for DiagnosticArgFromDisplay<'_> {
22     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
23         self.0.to_string().into_diagnostic_arg()
24     }
25 }
26
27 impl<'a> From<&'a dyn fmt::Display> for DiagnosticArgFromDisplay<'a> {
28     fn from(t: &'a dyn fmt::Display) -> Self {
29         DiagnosticArgFromDisplay(t)
30     }
31 }
32
33 impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> {
34     fn from(t: &'a T) -> Self {
35         DiagnosticArgFromDisplay(t)
36     }
37 }
38
39 macro_rules! into_diagnostic_arg_using_display {
40     ($( $ty:ty ),+ $(,)?) => {
41         $(
42             impl IntoDiagnosticArg for $ty {
43                 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
44                     self.to_string().into_diagnostic_arg()
45                 }
46             }
47         )+
48     }
49 }
50
51 into_diagnostic_arg_using_display!(
52     i8,
53     u8,
54     i16,
55     u16,
56     i32,
57     u32,
58     i64,
59     u64,
60     i128,
61     u128,
62     std::io::Error,
63     std::boxed::Box<dyn std::error::Error>,
64     std::num::NonZeroU32,
65     hir::Target,
66     Edition,
67     Ident,
68     MacroRulesNormalizedIdent,
69     ParseIntError,
70     StackProtector,
71     &TargetTriple,
72     SplitDebuginfo,
73     ExitStatus,
74 );
75
76 impl IntoDiagnosticArg for bool {
77     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
78         if self {
79             DiagnosticArgValue::Str(Cow::Borrowed("true"))
80         } else {
81             DiagnosticArgValue::Str(Cow::Borrowed("false"))
82         }
83     }
84 }
85
86 impl IntoDiagnosticArg for char {
87     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
88         DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
89     }
90 }
91
92 impl IntoDiagnosticArg for Symbol {
93     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
94         self.to_ident_string().into_diagnostic_arg()
95     }
96 }
97
98 impl<'a> IntoDiagnosticArg for &'a str {
99     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
100         self.to_string().into_diagnostic_arg()
101     }
102 }
103
104 impl IntoDiagnosticArg for String {
105     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
106         DiagnosticArgValue::Str(Cow::Owned(self))
107     }
108 }
109
110 impl<'a> IntoDiagnosticArg for Cow<'a, str> {
111     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
112         DiagnosticArgValue::Str(Cow::Owned(self.into_owned()))
113     }
114 }
115
116 impl<'a> IntoDiagnosticArg for &'a Path {
117     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
118         DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
119     }
120 }
121
122 impl IntoDiagnosticArg for PathBuf {
123     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
124         DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
125     }
126 }
127
128 impl IntoDiagnosticArg for usize {
129     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
130         DiagnosticArgValue::Number(self)
131     }
132 }
133
134 impl IntoDiagnosticArg for PanicStrategy {
135     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
136         DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
137     }
138 }
139
140 impl IntoDiagnosticArg for hir::ConstContext {
141     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
142         DiagnosticArgValue::Str(Cow::Borrowed(match self {
143             hir::ConstContext::ConstFn => "constant function",
144             hir::ConstContext::Static(_) => "static",
145             hir::ConstContext::Const => "constant",
146         }))
147     }
148 }
149
150 impl IntoDiagnosticArg for ast::Path {
151     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
152         DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
153     }
154 }
155
156 impl IntoDiagnosticArg for ast::token::Token {
157     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
158         DiagnosticArgValue::Str(pprust::token_to_string(&self))
159     }
160 }
161
162 impl IntoDiagnosticArg for ast::token::TokenKind {
163     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
164         DiagnosticArgValue::Str(pprust::token_kind_to_string(&self))
165     }
166 }
167
168 impl IntoDiagnosticArg for Level {
169     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
170         DiagnosticArgValue::Str(Cow::Borrowed(match self {
171             Level::Allow => "-A",
172             Level::Warn => "-W",
173             Level::ForceWarn(_) => "--force-warn",
174             Level::Deny => "-D",
175             Level::Forbid => "-F",
176             Level::Expect(_) => {
177                 unreachable!("lints with the level of `expect` should not run this code");
178             }
179         }))
180     }
181 }
182
183 #[derive(Clone)]
184 pub struct DiagnosticSymbolList(Vec<Symbol>);
185
186 impl From<Vec<Symbol>> for DiagnosticSymbolList {
187     fn from(v: Vec<Symbol>) -> Self {
188         DiagnosticSymbolList(v)
189     }
190 }
191
192 impl IntoDiagnosticArg for DiagnosticSymbolList {
193     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
194         // FIXME: replace the logic here with a real list formatter
195         let symbols = match &self.0[..] {
196             [symbol] => format!("`{symbol}`"),
197             [symbol, last] => {
198                 format!("`{symbol}` and `{last}`",)
199             }
200             [symbols @ .., last] => {
201                 let mut result = String::new();
202                 for symbol in symbols {
203                     write!(result, "`{symbol}`, ").unwrap();
204                 }
205                 write!(result, "and `{last}`").unwrap();
206                 result
207             }
208             [] => unreachable!(),
209         };
210         DiagnosticArgValue::Str(Cow::Owned(symbols))
211     }
212 }
213
214 impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
215     fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
216         let mut diag;
217         match self {
218             TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
219                 diag = handler.struct_fatal(fluent::errors_target_invalid_address_space);
220                 diag.set_arg("addr_space", addr_space);
221                 diag.set_arg("cause", cause);
222                 diag.set_arg("err", err);
223                 diag
224             }
225             TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
226                 diag = handler.struct_fatal(fluent::errors_target_invalid_bits);
227                 diag.set_arg("kind", kind);
228                 diag.set_arg("bit", bit);
229                 diag.set_arg("cause", cause);
230                 diag.set_arg("err", err);
231                 diag
232             }
233             TargetDataLayoutErrors::MissingAlignment { cause } => {
234                 diag = handler.struct_fatal(fluent::errors_target_missing_alignment);
235                 diag.set_arg("cause", cause);
236                 diag
237             }
238             TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
239                 diag = handler.struct_fatal(fluent::errors_target_invalid_alignment);
240                 diag.set_arg("cause", cause);
241                 diag.set_arg("err", err);
242                 diag
243             }
244             TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
245                 diag = handler.struct_fatal(fluent::errors_target_inconsistent_architecture);
246                 diag.set_arg("dl", dl);
247                 diag.set_arg("target", target);
248                 diag
249             }
250             TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
251                 diag = handler.struct_fatal(fluent::errors_target_inconsistent_pointer_width);
252                 diag.set_arg("pointer_size", pointer_size);
253                 diag.set_arg("target", target);
254                 diag
255             }
256             TargetDataLayoutErrors::InvalidBitsSize { err } => {
257                 diag = handler.struct_fatal(fluent::errors_target_invalid_bits_size);
258                 diag.set_arg("err", err);
259                 diag
260             }
261         }
262     }
263 }