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