• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
8 use rustc_macros::Diagnostic;
9 use rustc_span::{BytePos, 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 pub struct FeatureGateError {
31     pub span: MultiSpan,
32     pub explain: DiagnosticMessage,
33 }
34 
35 impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
36     #[track_caller]
into_diagnostic( self, handler: &'a rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'a, T>37     fn into_diagnostic(
38         self,
39         handler: &'a rustc_errors::Handler,
40     ) -> rustc_errors::DiagnosticBuilder<'a, T> {
41         let mut diag = handler.struct_diagnostic(self.explain);
42         diag.set_span(self.span);
43         diag.code(error_code!(E0658));
44         diag
45     }
46 }
47 
48 #[derive(Subdiagnostic)]
49 #[note(session_feature_diagnostic_for_issue)]
50 pub struct FeatureDiagnosticForIssue {
51     pub n: NonZeroU32,
52 }
53 
54 #[derive(Subdiagnostic)]
55 #[help(session_feature_diagnostic_help)]
56 pub struct FeatureDiagnosticHelp {
57     pub feature: Symbol,
58 }
59 
60 #[derive(Diagnostic)]
61 #[diag(session_not_circumvent_feature)]
62 pub struct NotCircumventFeature;
63 
64 #[derive(Diagnostic)]
65 #[diag(session_linker_plugin_lto_windows_not_supported)]
66 pub struct LinkerPluginToWindowsNotSupported;
67 
68 #[derive(Diagnostic)]
69 #[diag(session_profile_use_file_does_not_exist)]
70 pub struct ProfileUseFileDoesNotExist<'a> {
71     pub path: &'a std::path::Path,
72 }
73 
74 #[derive(Diagnostic)]
75 #[diag(session_profile_sample_use_file_does_not_exist)]
76 pub struct ProfileSampleUseFileDoesNotExist<'a> {
77     pub path: &'a std::path::Path,
78 }
79 
80 #[derive(Diagnostic)]
81 #[diag(session_target_requires_unwind_tables)]
82 pub struct TargetRequiresUnwindTables;
83 
84 #[derive(Diagnostic)]
85 #[diag(session_instrumentation_not_supported)]
86 pub struct InstrumentationNotSupported {
87     pub us: String,
88 }
89 
90 #[derive(Diagnostic)]
91 #[diag(session_sanitizer_not_supported)]
92 pub struct SanitizerNotSupported {
93     pub us: String,
94 }
95 
96 #[derive(Diagnostic)]
97 #[diag(session_sanitizers_not_supported)]
98 pub struct SanitizersNotSupported {
99     pub us: String,
100 }
101 
102 #[derive(Diagnostic)]
103 #[diag(session_cannot_mix_and_match_sanitizers)]
104 pub struct CannotMixAndMatchSanitizers {
105     pub first: String,
106     pub second: String,
107 }
108 
109 #[derive(Diagnostic)]
110 #[diag(session_cannot_enable_crt_static_linux)]
111 pub struct CannotEnableCrtStaticLinux;
112 
113 #[derive(Diagnostic)]
114 #[diag(session_sanitizer_cfi_requires_lto)]
115 pub struct SanitizerCfiRequiresLto;
116 
117 #[derive(Diagnostic)]
118 #[diag(session_sanitizer_cfi_canonical_jump_tables_requires_cfi)]
119 pub struct SanitizerCfiCanonicalJumpTablesRequiresCfi;
120 
121 #[derive(Diagnostic)]
122 #[diag(session_sanitizer_cfi_generalize_pointers_requires_cfi)]
123 pub struct SanitizerCfiGeneralizePointersRequiresCfi;
124 
125 #[derive(Diagnostic)]
126 #[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)]
127 pub struct SanitizerCfiNormalizeIntegersRequiresCfi;
128 
129 #[derive(Diagnostic)]
130 #[diag(session_split_lto_unit_requires_lto)]
131 pub struct SplitLtoUnitRequiresLto;
132 
133 #[derive(Diagnostic)]
134 #[diag(session_unstable_virtual_function_elimination)]
135 pub struct UnstableVirtualFunctionElimination;
136 
137 #[derive(Diagnostic)]
138 #[diag(session_unsupported_dwarf_version)]
139 pub struct UnsupportedDwarfVersion {
140     pub dwarf_version: u32,
141 }
142 
143 #[derive(Diagnostic)]
144 #[diag(session_target_stack_protector_not_supported)]
145 pub struct StackProtectorNotSupportedForTarget<'a> {
146     pub stack_protector: StackProtector,
147     pub target_triple: &'a TargetTriple,
148 }
149 
150 #[derive(Diagnostic)]
151 #[diag(session_branch_protection_requires_aarch64)]
152 pub(crate) struct BranchProtectionRequiresAArch64;
153 
154 #[derive(Diagnostic)]
155 #[diag(session_split_debuginfo_unstable_platform)]
156 pub struct SplitDebugInfoUnstablePlatform {
157     pub debuginfo: SplitDebuginfo,
158 }
159 
160 #[derive(Diagnostic)]
161 #[diag(session_file_is_not_writeable)]
162 pub struct FileIsNotWriteable<'a> {
163     pub file: &'a std::path::Path,
164 }
165 
166 #[derive(Diagnostic)]
167 #[diag(session_crate_name_does_not_match)]
168 pub struct CrateNameDoesNotMatch {
169     #[primary_span]
170     pub span: Span,
171     pub s: Symbol,
172     pub name: Symbol,
173 }
174 
175 #[derive(Diagnostic)]
176 #[diag(session_crate_name_invalid)]
177 pub struct CrateNameInvalid<'a> {
178     pub s: &'a str,
179 }
180 
181 #[derive(Diagnostic)]
182 #[diag(session_crate_name_empty)]
183 pub struct CrateNameEmpty {
184     #[primary_span]
185     pub span: Option<Span>,
186 }
187 
188 #[derive(Diagnostic)]
189 #[diag(session_invalid_character_in_create_name)]
190 pub struct InvalidCharacterInCrateName {
191     #[primary_span]
192     pub span: Option<Span>,
193     pub character: char,
194     pub crate_name: Symbol,
195 }
196 
197 #[derive(Subdiagnostic)]
198 #[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
199 pub struct ExprParenthesesNeeded {
200     #[suggestion_part(code = "(")]
201     pub left: Span,
202     #[suggestion_part(code = ")")]
203     pub right: Span,
204 }
205 
206 impl ExprParenthesesNeeded {
surrounding(s: Span) -> Self207     pub fn surrounding(s: Span) -> Self {
208         ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
209     }
210 }
211 
212 #[derive(Diagnostic)]
213 #[diag(session_skipping_const_checks)]
214 pub struct SkippingConstChecks {
215     #[subdiagnostic]
216     pub unleashed_features: Vec<UnleashedFeatureHelp>,
217 }
218 
219 #[derive(Subdiagnostic)]
220 pub enum UnleashedFeatureHelp {
221     #[help(session_unleashed_feature_help_named)]
222     Named {
223         #[primary_span]
224         span: Span,
225         gate: Symbol,
226     },
227     #[help(session_unleashed_feature_help_unnamed)]
228     Unnamed {
229         #[primary_span]
230         span: Span,
231     },
232 }
233 
234 #[derive(Diagnostic)]
235 #[diag(session_invalid_literal_suffix)]
236 pub(crate) struct InvalidLiteralSuffix<'a> {
237     #[primary_span]
238     #[label]
239     pub span: Span,
240     // FIXME(#100717)
241     pub kind: &'a str,
242     pub suffix: Symbol,
243 }
244 
245 #[derive(Diagnostic)]
246 #[diag(session_invalid_int_literal_width)]
247 #[help]
248 pub(crate) struct InvalidIntLiteralWidth {
249     #[primary_span]
250     pub span: Span,
251     pub width: String,
252 }
253 
254 #[derive(Diagnostic)]
255 #[diag(session_invalid_num_literal_base_prefix)]
256 #[note]
257 pub(crate) struct InvalidNumLiteralBasePrefix {
258     #[primary_span]
259     #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
260     pub span: Span,
261     pub fixed: String,
262 }
263 
264 #[derive(Diagnostic)]
265 #[diag(session_invalid_num_literal_suffix)]
266 #[help]
267 pub(crate) struct InvalidNumLiteralSuffix {
268     #[primary_span]
269     #[label]
270     pub span: Span,
271     pub suffix: String,
272 }
273 
274 #[derive(Diagnostic)]
275 #[diag(session_invalid_float_literal_width)]
276 #[help]
277 pub(crate) struct InvalidFloatLiteralWidth {
278     #[primary_span]
279     pub span: Span,
280     pub width: String,
281 }
282 
283 #[derive(Diagnostic)]
284 #[diag(session_invalid_float_literal_suffix)]
285 #[help]
286 pub(crate) struct InvalidFloatLiteralSuffix {
287     #[primary_span]
288     #[label]
289     pub span: Span,
290     pub suffix: String,
291 }
292 
293 #[derive(Diagnostic)]
294 #[diag(session_int_literal_too_large)]
295 #[note]
296 pub(crate) struct IntLiteralTooLarge {
297     #[primary_span]
298     pub span: Span,
299     pub limit: String,
300 }
301 
302 #[derive(Diagnostic)]
303 #[diag(session_hexadecimal_float_literal_not_supported)]
304 pub(crate) struct HexadecimalFloatLiteralNotSupported {
305     #[primary_span]
306     #[label(session_not_supported)]
307     pub span: Span,
308 }
309 
310 #[derive(Diagnostic)]
311 #[diag(session_octal_float_literal_not_supported)]
312 pub(crate) struct OctalFloatLiteralNotSupported {
313     #[primary_span]
314     #[label(session_not_supported)]
315     pub span: Span,
316 }
317 
318 #[derive(Diagnostic)]
319 #[diag(session_binary_float_literal_not_supported)]
320 pub(crate) struct BinaryFloatLiteralNotSupported {
321     #[primary_span]
322     #[label(session_not_supported)]
323     pub span: Span,
324 }
325 
326 #[derive(Diagnostic)]
327 #[diag(session_nul_in_c_str)]
328 pub(crate) struct NulInCStr {
329     #[primary_span]
330     pub span: Span,
331 }
332 
report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span)333 pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
334     // Checks if `s` looks like i32 or u1234 etc.
335     fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
336         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
337     }
338 
339     // Try to lowercase the prefix if the prefix and suffix are valid.
340     fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
341         let mut chars = suffix.chars();
342 
343         let base_char = chars.next().unwrap();
344         let base = match base_char {
345             'B' => 2,
346             'O' => 8,
347             'X' => 16,
348             _ => return None,
349         };
350 
351         // check that the suffix contains only base-appropriate characters
352         let valid = prefix == "0"
353             && chars
354                 .filter(|c| *c != '_')
355                 .take_while(|c| *c != 'i' && *c != 'u')
356                 .all(|c| c.to_digit(base).is_some());
357 
358         valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
359     }
360 
361     let token::Lit { kind, symbol, suffix, .. } = lit;
362     match err {
363         // `LexerError` is an error, but it was already reported
364         // by lexer, so here we don't report it the second time.
365         LitError::LexerError => {}
366         LitError::InvalidSuffix => {
367             if let Some(suffix) = suffix {
368                 sess.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
369             }
370         }
371         LitError::InvalidIntSuffix => {
372             let suf = suffix.expect("suffix error with no suffix");
373             let suf = suf.as_str();
374             if looks_like_width_suffix(&['i', 'u'], suf) {
375                 // If it looks like a width, try to be helpful.
376                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
377             } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
378                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
379             } else {
380                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
381             }
382         }
383         LitError::InvalidFloatSuffix => {
384             let suf = suffix.expect("suffix error with no suffix");
385             let suf = suf.as_str();
386             if looks_like_width_suffix(&['f'], suf) {
387                 // If it looks like a width, try to be helpful.
388                 sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
389             } else {
390                 sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
391             }
392         }
393         LitError::NonDecimalFloat(base) => {
394             match base {
395                 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
396                 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }),
397                 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }),
398                 _ => unreachable!(),
399             };
400         }
401         LitError::IntTooLarge(base) => {
402             let max = u128::MAX;
403             let limit = match base {
404                 2 => format!("{max:#b}"),
405                 8 => format!("{max:#o}"),
406                 16 => format!("{max:#x}"),
407                 _ => format!("{max}"),
408             };
409             sess.emit_err(IntLiteralTooLarge { span, limit });
410         }
411         LitError::NulInCStr(range) => {
412             let lo = BytePos(span.lo().0 + range.start as u32 + 2);
413             let hi = BytePos(span.lo().0 + range.end as u32 + 2);
414             let span = span.with_lo(lo).with_hi(hi);
415             sess.emit_err(NulInCStr { span });
416         }
417     }
418 }
419 
420 #[derive(Diagnostic)]
421 #[diag(session_optimization_fuel_exhausted)]
422 pub struct OptimisationFuelExhausted {
423     pub msg: String,
424 }
425 
426 #[derive(Diagnostic)]
427 #[diag(session_incompatible_linker_flavor)]
428 #[note]
429 pub struct IncompatibleLinkerFlavor {
430     pub flavor: &'static str,
431     pub compatible_list: String,
432 }
433