]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_session/src/errors.rs
drive-by: Fix path spans
[rust.git] / compiler / rustc_session / src / errors.rs
1 use std::num::NonZeroU32;
2
3 use crate::cgu_reuse_tracker::CguReuse;
4 use crate::parse::ParseSess;
5 use rustc_ast::token;
6 use rustc_ast::util::literal::LitError;
7 use rustc_errors::MultiSpan;
8 use rustc_macros::Diagnostic;
9 use rustc_span::{Span, Symbol};
10 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
11
12 #[derive(Diagnostic)]
13 #[diag(session_incorrect_cgu_reuse_type)]
14 pub struct IncorrectCguReuseType<'a> {
15     #[primary_span]
16     pub span: Span,
17     pub cgu_user_name: &'a str,
18     pub actual_reuse: CguReuse,
19     pub expected_reuse: CguReuse,
20     pub at_least: u8,
21 }
22
23 #[derive(Diagnostic)]
24 #[diag(session_cgu_not_recorded)]
25 pub struct CguNotRecorded<'a> {
26     pub cgu_user_name: &'a str,
27     pub cgu_name: &'a str,
28 }
29
30 #[derive(Diagnostic)]
31 #[diag(session_feature_gate_error, code = "E0658")]
32 pub struct FeatureGateError<'a> {
33     #[primary_span]
34     pub span: MultiSpan,
35     pub explain: &'a str,
36 }
37
38 #[derive(Subdiagnostic)]
39 #[note(session_feature_diagnostic_for_issue)]
40 pub struct FeatureDiagnosticForIssue {
41     pub n: NonZeroU32,
42 }
43
44 #[derive(Subdiagnostic)]
45 #[help(session_feature_diagnostic_help)]
46 pub struct FeatureDiagnosticHelp {
47     pub feature: Symbol,
48 }
49
50 #[derive(Diagnostic)]
51 #[diag(session_not_circumvent_feature)]
52 pub struct NotCircumventFeature;
53
54 #[derive(Diagnostic)]
55 #[diag(session_linker_plugin_lto_windows_not_supported)]
56 pub struct LinkerPluginToWindowsNotSupported;
57
58 #[derive(Diagnostic)]
59 #[diag(session_profile_use_file_does_not_exist)]
60 pub struct ProfileUseFileDoesNotExist<'a> {
61     pub path: &'a std::path::Path,
62 }
63
64 #[derive(Diagnostic)]
65 #[diag(session_profile_sample_use_file_does_not_exist)]
66 pub struct ProfileSampleUseFileDoesNotExist<'a> {
67     pub path: &'a std::path::Path,
68 }
69
70 #[derive(Diagnostic)]
71 #[diag(session_target_requires_unwind_tables)]
72 pub struct TargetRequiresUnwindTables;
73
74 #[derive(Diagnostic)]
75 #[diag(session_sanitizer_not_supported)]
76 pub struct SanitizerNotSupported {
77     pub us: String,
78 }
79
80 #[derive(Diagnostic)]
81 #[diag(session_sanitizers_not_supported)]
82 pub struct SanitizersNotSupported {
83     pub us: String,
84 }
85
86 #[derive(Diagnostic)]
87 #[diag(session_cannot_mix_and_match_sanitizers)]
88 pub struct CannotMixAndMatchSanitizers {
89     pub first: String,
90     pub second: String,
91 }
92
93 #[derive(Diagnostic)]
94 #[diag(session_cannot_enable_crt_static_linux)]
95 pub struct CannotEnableCrtStaticLinux;
96
97 #[derive(Diagnostic)]
98 #[diag(session_sanitizer_cfi_enabled)]
99 pub struct SanitizerCfiEnabled;
100
101 #[derive(Diagnostic)]
102 #[diag(session_unstable_virtual_function_elimination)]
103 pub struct UnstableVirtualFunctionElimination;
104
105 #[derive(Diagnostic)]
106 #[diag(session_unsupported_dwarf_version)]
107 pub struct UnsupportedDwarfVersion {
108     pub dwarf_version: u32,
109 }
110
111 #[derive(Diagnostic)]
112 #[diag(session_target_stack_protector_not_supported)]
113 pub struct StackProtectorNotSupportedForTarget<'a> {
114     pub stack_protector: StackProtector,
115     pub target_triple: &'a TargetTriple,
116 }
117
118 #[derive(Diagnostic)]
119 #[diag(session_split_debuginfo_unstable_platform)]
120 pub struct SplitDebugInfoUnstablePlatform {
121     pub debuginfo: SplitDebuginfo,
122 }
123
124 #[derive(Diagnostic)]
125 #[diag(session_file_is_not_writeable)]
126 pub struct FileIsNotWriteable<'a> {
127     pub file: &'a std::path::Path,
128 }
129
130 #[derive(Diagnostic)]
131 #[diag(session_crate_name_does_not_match)]
132 pub struct CrateNameDoesNotMatch {
133     #[primary_span]
134     pub span: Span,
135     pub s: Symbol,
136     pub name: Symbol,
137 }
138
139 #[derive(Diagnostic)]
140 #[diag(session_crate_name_invalid)]
141 pub struct CrateNameInvalid<'a> {
142     pub s: &'a str,
143 }
144
145 #[derive(Diagnostic)]
146 #[diag(session_crate_name_empty)]
147 pub struct CrateNameEmpty {
148     #[primary_span]
149     pub span: Option<Span>,
150 }
151
152 #[derive(Diagnostic)]
153 #[diag(session_invalid_character_in_create_name)]
154 pub struct InvalidCharacterInCrateName {
155     #[primary_span]
156     pub span: Option<Span>,
157     pub character: char,
158     pub crate_name: Symbol,
159 }
160
161 #[derive(Subdiagnostic)]
162 #[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
163 pub struct ExprParenthesesNeeded {
164     #[suggestion_part(code = "(")]
165     pub left: Span,
166     #[suggestion_part(code = ")")]
167     pub right: Span,
168 }
169
170 impl ExprParenthesesNeeded {
171     pub fn surrounding(s: Span) -> Self {
172         ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
173     }
174 }
175
176 #[derive(Diagnostic)]
177 #[diag(session_skipping_const_checks)]
178 pub struct SkippingConstChecks {
179     #[subdiagnostic(eager)]
180     pub unleashed_features: Vec<UnleashedFeatureHelp>,
181 }
182
183 #[derive(Subdiagnostic)]
184 pub enum UnleashedFeatureHelp {
185     #[help(session_unleashed_feature_help_named)]
186     Named {
187         #[primary_span]
188         span: Span,
189         gate: Symbol,
190     },
191     #[help(session_unleashed_feature_help_unnamed)]
192     Unnamed {
193         #[primary_span]
194         span: Span,
195     },
196 }
197
198 #[derive(Diagnostic)]
199 #[diag(session_invalid_literal_suffix)]
200 pub(crate) struct InvalidLiteralSuffix<'a> {
201     #[primary_span]
202     #[label]
203     pub span: Span,
204     // FIXME(#100717)
205     pub kind: &'a str,
206     pub suffix: Symbol,
207 }
208
209 #[derive(Diagnostic)]
210 #[diag(session_invalid_int_literal_width)]
211 #[help]
212 pub(crate) struct InvalidIntLiteralWidth {
213     #[primary_span]
214     pub span: Span,
215     pub width: String,
216 }
217
218 #[derive(Diagnostic)]
219 #[diag(session_invalid_num_literal_base_prefix)]
220 #[note]
221 pub(crate) struct InvalidNumLiteralBasePrefix {
222     #[primary_span]
223     #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
224     pub span: Span,
225     pub fixed: String,
226 }
227
228 #[derive(Diagnostic)]
229 #[diag(session_invalid_num_literal_suffix)]
230 #[help]
231 pub(crate) struct InvalidNumLiteralSuffix {
232     #[primary_span]
233     #[label]
234     pub span: Span,
235     pub suffix: String,
236 }
237
238 #[derive(Diagnostic)]
239 #[diag(session_invalid_float_literal_width)]
240 #[help]
241 pub(crate) struct InvalidFloatLiteralWidth {
242     #[primary_span]
243     pub span: Span,
244     pub width: String,
245 }
246
247 #[derive(Diagnostic)]
248 #[diag(session_invalid_float_literal_suffix)]
249 #[help]
250 pub(crate) struct InvalidFloatLiteralSuffix {
251     #[primary_span]
252     #[label]
253     pub span: Span,
254     pub suffix: String,
255 }
256
257 #[derive(Diagnostic)]
258 #[diag(session_int_literal_too_large)]
259 pub(crate) struct IntLiteralTooLarge {
260     #[primary_span]
261     pub span: Span,
262 }
263
264 #[derive(Diagnostic)]
265 #[diag(session_hexadecimal_float_literal_not_supported)]
266 pub(crate) struct HexadecimalFloatLiteralNotSupported {
267     #[primary_span]
268     #[label(session_not_supported)]
269     pub span: Span,
270 }
271
272 #[derive(Diagnostic)]
273 #[diag(session_octal_float_literal_not_supported)]
274 pub(crate) struct OctalFloatLiteralNotSupported {
275     #[primary_span]
276     #[label(session_not_supported)]
277     pub span: Span,
278 }
279
280 #[derive(Diagnostic)]
281 #[diag(session_binary_float_literal_not_supported)]
282 pub(crate) struct BinaryFloatLiteralNotSupported {
283     #[primary_span]
284     #[label(session_not_supported)]
285     pub span: Span,
286 }
287
288 pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
289     // Checks if `s` looks like i32 or u1234 etc.
290     fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
291         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
292     }
293
294     // Try to lowercase the prefix if the prefix and suffix are valid.
295     fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
296         let mut chars = suffix.chars();
297
298         let base_char = chars.next().unwrap();
299         let base = match base_char {
300             'B' => 2,
301             'O' => 8,
302             'X' => 16,
303             _ => return None,
304         };
305
306         // check that the suffix contains only base-appropriate characters
307         let valid = prefix == "0"
308             && chars
309                 .filter(|c| *c != '_')
310                 .take_while(|c| *c != 'i' && *c != 'u')
311                 .all(|c| c.to_digit(base).is_some());
312
313         if valid {
314             Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
315         } else {
316             None
317         }
318     }
319
320     let token::Lit { kind, symbol, suffix, .. } = lit;
321     match err {
322         // `LexerError` is an error, but it was already reported
323         // by lexer, so here we don't report it the second time.
324         LitError::LexerError => {}
325         LitError::InvalidSuffix => {
326             if let Some(suffix) = suffix {
327                 sess.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
328             }
329         }
330         LitError::InvalidIntSuffix => {
331             let suf = suffix.expect("suffix error with no suffix");
332             let suf = suf.as_str();
333             if looks_like_width_suffix(&['i', 'u'], suf) {
334                 // If it looks like a width, try to be helpful.
335                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
336             } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
337                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
338             } else {
339                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
340             }
341         }
342         LitError::InvalidFloatSuffix => {
343             let suf = suffix.expect("suffix error with no suffix");
344             let suf = suf.as_str();
345             if looks_like_width_suffix(&['f'], suf) {
346                 // If it looks like a width, try to be helpful.
347                 sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
348             } else {
349                 sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
350             }
351         }
352         LitError::NonDecimalFloat(base) => {
353             match base {
354                 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
355                 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }),
356                 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }),
357                 _ => unreachable!(),
358             };
359         }
360         LitError::IntTooLarge => {
361             sess.emit_err(IntLiteralTooLarge { span });
362         }
363     }
364 }