]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_session/src/errors.rs
Rollup merge of #106699 - eholk:await-chains-drop-tracking, r=wesleywiser
[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_branch_protection_requires_aarch64)]
120 pub(crate) struct BranchProtectionRequiresAArch64;
121
122 #[derive(Diagnostic)]
123 #[diag(session_split_debuginfo_unstable_platform)]
124 pub struct SplitDebugInfoUnstablePlatform {
125     pub debuginfo: SplitDebuginfo,
126 }
127
128 #[derive(Diagnostic)]
129 #[diag(session_file_is_not_writeable)]
130 pub struct FileIsNotWriteable<'a> {
131     pub file: &'a std::path::Path,
132 }
133
134 #[derive(Diagnostic)]
135 #[diag(session_crate_name_does_not_match)]
136 pub struct CrateNameDoesNotMatch {
137     #[primary_span]
138     pub span: Span,
139     pub s: Symbol,
140     pub name: Symbol,
141 }
142
143 #[derive(Diagnostic)]
144 #[diag(session_crate_name_invalid)]
145 pub struct CrateNameInvalid<'a> {
146     pub s: &'a str,
147 }
148
149 #[derive(Diagnostic)]
150 #[diag(session_crate_name_empty)]
151 pub struct CrateNameEmpty {
152     #[primary_span]
153     pub span: Option<Span>,
154 }
155
156 #[derive(Diagnostic)]
157 #[diag(session_invalid_character_in_create_name)]
158 pub struct InvalidCharacterInCrateName {
159     #[primary_span]
160     pub span: Option<Span>,
161     pub character: char,
162     pub crate_name: Symbol,
163 }
164
165 #[derive(Subdiagnostic)]
166 #[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
167 pub struct ExprParenthesesNeeded {
168     #[suggestion_part(code = "(")]
169     pub left: Span,
170     #[suggestion_part(code = ")")]
171     pub right: Span,
172 }
173
174 impl ExprParenthesesNeeded {
175     pub fn surrounding(s: Span) -> Self {
176         ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
177     }
178 }
179
180 #[derive(Diagnostic)]
181 #[diag(session_skipping_const_checks)]
182 pub struct SkippingConstChecks {
183     #[subdiagnostic]
184     pub unleashed_features: Vec<UnleashedFeatureHelp>,
185 }
186
187 #[derive(Subdiagnostic)]
188 pub enum UnleashedFeatureHelp {
189     #[help(session_unleashed_feature_help_named)]
190     Named {
191         #[primary_span]
192         span: Span,
193         gate: Symbol,
194     },
195     #[help(session_unleashed_feature_help_unnamed)]
196     Unnamed {
197         #[primary_span]
198         span: Span,
199     },
200 }
201
202 #[derive(Diagnostic)]
203 #[diag(session_invalid_literal_suffix)]
204 pub(crate) struct InvalidLiteralSuffix<'a> {
205     #[primary_span]
206     #[label]
207     pub span: Span,
208     // FIXME(#100717)
209     pub kind: &'a str,
210     pub suffix: Symbol,
211 }
212
213 #[derive(Diagnostic)]
214 #[diag(session_invalid_int_literal_width)]
215 #[help]
216 pub(crate) struct InvalidIntLiteralWidth {
217     #[primary_span]
218     pub span: Span,
219     pub width: String,
220 }
221
222 #[derive(Diagnostic)]
223 #[diag(session_invalid_num_literal_base_prefix)]
224 #[note]
225 pub(crate) struct InvalidNumLiteralBasePrefix {
226     #[primary_span]
227     #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
228     pub span: Span,
229     pub fixed: String,
230 }
231
232 #[derive(Diagnostic)]
233 #[diag(session_invalid_num_literal_suffix)]
234 #[help]
235 pub(crate) struct InvalidNumLiteralSuffix {
236     #[primary_span]
237     #[label]
238     pub span: Span,
239     pub suffix: String,
240 }
241
242 #[derive(Diagnostic)]
243 #[diag(session_invalid_float_literal_width)]
244 #[help]
245 pub(crate) struct InvalidFloatLiteralWidth {
246     #[primary_span]
247     pub span: Span,
248     pub width: String,
249 }
250
251 #[derive(Diagnostic)]
252 #[diag(session_invalid_float_literal_suffix)]
253 #[help]
254 pub(crate) struct InvalidFloatLiteralSuffix {
255     #[primary_span]
256     #[label]
257     pub span: Span,
258     pub suffix: String,
259 }
260
261 #[derive(Diagnostic)]
262 #[diag(session_int_literal_too_large)]
263 #[note]
264 pub(crate) struct IntLiteralTooLarge {
265     #[primary_span]
266     pub span: Span,
267     pub limit: String,
268 }
269
270 #[derive(Diagnostic)]
271 #[diag(session_hexadecimal_float_literal_not_supported)]
272 pub(crate) struct HexadecimalFloatLiteralNotSupported {
273     #[primary_span]
274     #[label(session_not_supported)]
275     pub span: Span,
276 }
277
278 #[derive(Diagnostic)]
279 #[diag(session_octal_float_literal_not_supported)]
280 pub(crate) struct OctalFloatLiteralNotSupported {
281     #[primary_span]
282     #[label(session_not_supported)]
283     pub span: Span,
284 }
285
286 #[derive(Diagnostic)]
287 #[diag(session_binary_float_literal_not_supported)]
288 pub(crate) struct BinaryFloatLiteralNotSupported {
289     #[primary_span]
290     #[label(session_not_supported)]
291     pub span: Span,
292 }
293
294 pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
295     // Checks if `s` looks like i32 or u1234 etc.
296     fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
297         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
298     }
299
300     // Try to lowercase the prefix if the prefix and suffix are valid.
301     fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
302         let mut chars = suffix.chars();
303
304         let base_char = chars.next().unwrap();
305         let base = match base_char {
306             'B' => 2,
307             'O' => 8,
308             'X' => 16,
309             _ => return None,
310         };
311
312         // check that the suffix contains only base-appropriate characters
313         let valid = prefix == "0"
314             && chars
315                 .filter(|c| *c != '_')
316                 .take_while(|c| *c != 'i' && *c != 'u')
317                 .all(|c| c.to_digit(base).is_some());
318
319         if valid {
320             Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
321         } else {
322             None
323         }
324     }
325
326     let token::Lit { kind, symbol, suffix, .. } = lit;
327     match err {
328         // `LexerError` is an error, but it was already reported
329         // by lexer, so here we don't report it the second time.
330         LitError::LexerError => {}
331         LitError::InvalidSuffix => {
332             if let Some(suffix) = suffix {
333                 sess.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
334             }
335         }
336         LitError::InvalidIntSuffix => {
337             let suf = suffix.expect("suffix error with no suffix");
338             let suf = suf.as_str();
339             if looks_like_width_suffix(&['i', 'u'], suf) {
340                 // If it looks like a width, try to be helpful.
341                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
342             } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
343                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
344             } else {
345                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
346             }
347         }
348         LitError::InvalidFloatSuffix => {
349             let suf = suffix.expect("suffix error with no suffix");
350             let suf = suf.as_str();
351             if looks_like_width_suffix(&['f'], suf) {
352                 // If it looks like a width, try to be helpful.
353                 sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
354             } else {
355                 sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
356             }
357         }
358         LitError::NonDecimalFloat(base) => {
359             match base {
360                 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
361                 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }),
362                 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }),
363                 _ => unreachable!(),
364             };
365         }
366         LitError::IntTooLarge(base) => {
367             let max = u128::MAX;
368             let limit = match base {
369                 2 => format!("{max:#b}"),
370                 8 => format!("{max:#o}"),
371                 16 => format!("{max:#x}"),
372                 _ => format!("{max}"),
373             };
374             sess.emit_err(IntLiteralTooLarge { span, limit });
375         }
376     }
377 }