rustc_session/
errors.rs

1use std::num::NonZero;
2
3use rustc_ast::token;
4use rustc_ast::util::literal::LitError;
5use rustc_errors::codes::*;
6use rustc_errors::{
7    Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level,
8    MultiSpan,
9};
10use rustc_macros::{Diagnostic, Subdiagnostic};
11use rustc_span::{Span, Symbol};
12use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple};
13
14use crate::config::CrateType;
15use crate::parse::ParseSess;
16
17pub(crate) struct FeatureGateError {
18    pub(crate) span: MultiSpan,
19    pub(crate) explain: DiagMessage,
20}
21
22impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError {
23    #[track_caller]
24    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
25        Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
26    }
27}
28
29#[derive(Subdiagnostic)]
30#[note(session_feature_diagnostic_for_issue)]
31pub(crate) struct FeatureDiagnosticForIssue {
32    pub(crate) n: NonZero<u32>,
33}
34
35#[derive(Subdiagnostic)]
36#[note(session_feature_suggest_upgrade_compiler)]
37pub(crate) struct SuggestUpgradeCompiler {
38    date: &'static str,
39}
40
41impl SuggestUpgradeCompiler {
42    pub(crate) fn ui_testing() -> Self {
43        Self { date: "YYYY-MM-DD" }
44    }
45
46    pub(crate) fn new() -> Option<Self> {
47        let date = option_env!("CFG_VER_DATE")?;
48
49        Some(Self { date })
50    }
51}
52
53#[derive(Subdiagnostic)]
54#[help(session_feature_diagnostic_help)]
55pub(crate) struct FeatureDiagnosticHelp {
56    pub(crate) feature: Symbol,
57}
58
59#[derive(Subdiagnostic)]
60#[suggestion(
61    session_feature_diagnostic_suggestion,
62    applicability = "maybe-incorrect",
63    code = "#![feature({feature})]\n"
64)]
65pub struct FeatureDiagnosticSuggestion {
66    pub feature: Symbol,
67    #[primary_span]
68    pub span: Span,
69}
70
71#[derive(Subdiagnostic)]
72#[help(session_cli_feature_diagnostic_help)]
73pub(crate) struct CliFeatureDiagnosticHelp {
74    pub(crate) feature: Symbol,
75}
76
77#[derive(Diagnostic)]
78#[diag(session_not_circumvent_feature)]
79pub(crate) struct NotCircumventFeature;
80
81#[derive(Diagnostic)]
82#[diag(session_linker_plugin_lto_windows_not_supported)]
83pub(crate) struct LinkerPluginToWindowsNotSupported;
84
85#[derive(Diagnostic)]
86#[diag(session_profile_use_file_does_not_exist)]
87pub(crate) struct ProfileUseFileDoesNotExist<'a> {
88    pub(crate) path: &'a std::path::Path,
89}
90
91#[derive(Diagnostic)]
92#[diag(session_profile_sample_use_file_does_not_exist)]
93pub(crate) struct ProfileSampleUseFileDoesNotExist<'a> {
94    pub(crate) path: &'a std::path::Path,
95}
96
97#[derive(Diagnostic)]
98#[diag(session_target_requires_unwind_tables)]
99pub(crate) struct TargetRequiresUnwindTables;
100
101#[derive(Diagnostic)]
102#[diag(session_instrumentation_not_supported)]
103pub(crate) struct InstrumentationNotSupported {
104    pub(crate) us: String,
105}
106
107#[derive(Diagnostic)]
108#[diag(session_sanitizer_not_supported)]
109pub(crate) struct SanitizerNotSupported {
110    pub(crate) us: String,
111}
112
113#[derive(Diagnostic)]
114#[diag(session_sanitizers_not_supported)]
115pub(crate) struct SanitizersNotSupported {
116    pub(crate) us: String,
117}
118
119#[derive(Diagnostic)]
120#[diag(session_cannot_mix_and_match_sanitizers)]
121pub(crate) struct CannotMixAndMatchSanitizers {
122    pub(crate) first: String,
123    pub(crate) second: String,
124}
125
126#[derive(Diagnostic)]
127#[diag(session_cannot_enable_crt_static_linux)]
128pub(crate) struct CannotEnableCrtStaticLinux;
129
130#[derive(Diagnostic)]
131#[diag(session_sanitizer_cfi_requires_lto)]
132pub(crate) struct SanitizerCfiRequiresLto;
133
134#[derive(Diagnostic)]
135#[diag(session_sanitizer_cfi_requires_single_codegen_unit)]
136pub(crate) struct SanitizerCfiRequiresSingleCodegenUnit;
137
138#[derive(Diagnostic)]
139#[diag(session_sanitizer_cfi_canonical_jump_tables_requires_cfi)]
140pub(crate) struct SanitizerCfiCanonicalJumpTablesRequiresCfi;
141
142#[derive(Diagnostic)]
143#[diag(session_sanitizer_cfi_generalize_pointers_requires_cfi)]
144pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi;
145
146#[derive(Diagnostic)]
147#[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)]
148pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi;
149
150#[derive(Diagnostic)]
151#[diag(session_sanitizer_kcfi_requires_panic_abort)]
152pub(crate) struct SanitizerKcfiRequiresPanicAbort;
153
154#[derive(Diagnostic)]
155#[diag(session_split_lto_unit_requires_lto)]
156pub(crate) struct SplitLtoUnitRequiresLto;
157
158#[derive(Diagnostic)]
159#[diag(session_unstable_virtual_function_elimination)]
160pub(crate) struct UnstableVirtualFunctionElimination;
161
162#[derive(Diagnostic)]
163#[diag(session_unsupported_dwarf_version)]
164#[help(session_unsupported_dwarf_version_help)]
165pub(crate) struct UnsupportedDwarfVersion {
166    pub(crate) dwarf_version: u32,
167}
168
169#[derive(Diagnostic)]
170#[diag(session_embed_source_insufficient_dwarf_version)]
171pub(crate) struct EmbedSourceInsufficientDwarfVersion {
172    pub(crate) dwarf_version: u32,
173}
174
175#[derive(Diagnostic)]
176#[diag(session_embed_source_requires_debug_info)]
177pub(crate) struct EmbedSourceRequiresDebugInfo;
178
179#[derive(Diagnostic)]
180#[diag(session_target_stack_protector_not_supported)]
181pub(crate) struct StackProtectorNotSupportedForTarget<'a> {
182    pub(crate) stack_protector: StackProtector,
183    pub(crate) target_triple: &'a TargetTuple,
184}
185
186#[derive(Diagnostic)]
187#[diag(session_target_small_data_threshold_not_supported)]
188pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> {
189    pub(crate) target_triple: &'a TargetTuple,
190}
191
192#[derive(Diagnostic)]
193#[diag(session_branch_protection_requires_aarch64)]
194pub(crate) struct BranchProtectionRequiresAArch64;
195
196#[derive(Diagnostic)]
197#[diag(session_split_debuginfo_unstable_platform)]
198pub(crate) struct SplitDebugInfoUnstablePlatform {
199    pub(crate) debuginfo: SplitDebuginfo,
200}
201
202#[derive(Diagnostic)]
203#[diag(session_file_is_not_writeable)]
204pub(crate) struct FileIsNotWriteable<'a> {
205    pub(crate) file: &'a std::path::Path,
206}
207
208#[derive(Diagnostic)]
209#[diag(session_file_write_fail)]
210pub(crate) struct FileWriteFail<'a> {
211    pub(crate) path: &'a std::path::Path,
212    pub(crate) err: String,
213}
214
215#[derive(Diagnostic)]
216#[diag(session_crate_name_does_not_match)]
217pub(crate) struct CrateNameDoesNotMatch {
218    #[primary_span]
219    pub(crate) span: Span,
220    pub(crate) s: Symbol,
221    pub(crate) name: Symbol,
222}
223
224#[derive(Diagnostic)]
225#[diag(session_crate_name_invalid)]
226pub(crate) struct CrateNameInvalid<'a> {
227    pub(crate) s: &'a str,
228}
229
230#[derive(Diagnostic)]
231#[diag(session_crate_name_empty)]
232pub(crate) struct CrateNameEmpty {
233    #[primary_span]
234    pub(crate) span: Option<Span>,
235}
236
237#[derive(Diagnostic)]
238#[diag(session_invalid_character_in_create_name)]
239pub(crate) struct InvalidCharacterInCrateName {
240    #[primary_span]
241    pub(crate) span: Option<Span>,
242    pub(crate) character: char,
243    pub(crate) crate_name: Symbol,
244    #[subdiagnostic]
245    pub(crate) crate_name_help: Option<InvalidCrateNameHelp>,
246}
247
248#[derive(Subdiagnostic)]
249pub(crate) enum InvalidCrateNameHelp {
250    #[help(session_invalid_character_in_create_name_help)]
251    AddCrateName,
252}
253
254#[derive(Subdiagnostic)]
255#[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
256pub struct ExprParenthesesNeeded {
257    #[suggestion_part(code = "(")]
258    left: Span,
259    #[suggestion_part(code = ")")]
260    right: Span,
261}
262
263impl ExprParenthesesNeeded {
264    pub fn surrounding(s: Span) -> Self {
265        ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
266    }
267}
268
269#[derive(Diagnostic)]
270#[diag(session_skipping_const_checks)]
271pub(crate) struct SkippingConstChecks {
272    #[subdiagnostic]
273    pub(crate) unleashed_features: Vec<UnleashedFeatureHelp>,
274}
275
276#[derive(Subdiagnostic)]
277pub(crate) enum UnleashedFeatureHelp {
278    #[help(session_unleashed_feature_help_named)]
279    Named {
280        #[primary_span]
281        span: Span,
282        gate: Symbol,
283    },
284    #[help(session_unleashed_feature_help_unnamed)]
285    Unnamed {
286        #[primary_span]
287        span: Span,
288    },
289}
290
291#[derive(Diagnostic)]
292#[diag(session_invalid_literal_suffix)]
293struct InvalidLiteralSuffix<'a> {
294    #[primary_span]
295    #[label]
296    span: Span,
297    // FIXME(#100717)
298    kind: &'a str,
299    suffix: Symbol,
300}
301
302#[derive(Diagnostic)]
303#[diag(session_invalid_int_literal_width)]
304#[help]
305struct InvalidIntLiteralWidth {
306    #[primary_span]
307    span: Span,
308    width: String,
309}
310
311#[derive(Diagnostic)]
312#[diag(session_invalid_num_literal_base_prefix)]
313#[note]
314struct InvalidNumLiteralBasePrefix {
315    #[primary_span]
316    #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
317    span: Span,
318    fixed: String,
319}
320
321#[derive(Diagnostic)]
322#[diag(session_invalid_num_literal_suffix)]
323#[help]
324struct InvalidNumLiteralSuffix {
325    #[primary_span]
326    #[label]
327    span: Span,
328    suffix: String,
329}
330
331#[derive(Diagnostic)]
332#[diag(session_invalid_float_literal_width)]
333#[help]
334struct InvalidFloatLiteralWidth {
335    #[primary_span]
336    span: Span,
337    width: String,
338}
339
340#[derive(Diagnostic)]
341#[diag(session_invalid_float_literal_suffix)]
342#[help]
343struct InvalidFloatLiteralSuffix {
344    #[primary_span]
345    #[label]
346    span: Span,
347    suffix: String,
348}
349
350#[derive(Diagnostic)]
351#[diag(session_int_literal_too_large)]
352#[note]
353struct IntLiteralTooLarge {
354    #[primary_span]
355    span: Span,
356    limit: String,
357}
358
359#[derive(Diagnostic)]
360#[diag(session_hexadecimal_float_literal_not_supported)]
361struct HexadecimalFloatLiteralNotSupported {
362    #[primary_span]
363    #[label(session_not_supported)]
364    span: Span,
365}
366
367#[derive(Diagnostic)]
368#[diag(session_octal_float_literal_not_supported)]
369struct OctalFloatLiteralNotSupported {
370    #[primary_span]
371    #[label(session_not_supported)]
372    span: Span,
373}
374
375#[derive(Diagnostic)]
376#[diag(session_binary_float_literal_not_supported)]
377struct BinaryFloatLiteralNotSupported {
378    #[primary_span]
379    #[label(session_not_supported)]
380    span: Span,
381}
382
383#[derive(Diagnostic)]
384#[diag(session_unsupported_crate_type_for_target)]
385pub(crate) struct UnsupportedCrateTypeForTarget<'a> {
386    pub(crate) crate_type: CrateType,
387    pub(crate) target_triple: &'a TargetTuple,
388}
389
390pub fn report_lit_error(
391    psess: &ParseSess,
392    err: LitError,
393    lit: token::Lit,
394    span: Span,
395) -> ErrorGuaranteed {
396    // Checks if `s` looks like i32 or u1234 etc.
397    fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
398        s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
399    }
400
401    // Try to lowercase the prefix if the prefix and suffix are valid.
402    fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
403        let mut chars = suffix.chars();
404
405        let base_char = chars.next().unwrap();
406        let base = match base_char {
407            'B' => 2,
408            'O' => 8,
409            'X' => 16,
410            _ => return None,
411        };
412
413        // check that the suffix contains only base-appropriate characters
414        let valid = prefix == "0"
415            && chars
416                .filter(|c| *c != '_')
417                .take_while(|c| *c != 'i' && *c != 'u')
418                .all(|c| c.to_digit(base).is_some());
419
420        valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
421    }
422
423    let dcx = psess.dcx();
424    match err {
425        LitError::InvalidSuffix(suffix) => {
426            dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
427        }
428        LitError::InvalidIntSuffix(suffix) => {
429            let suf = suffix.as_str();
430            if looks_like_width_suffix(&['i', 'u'], suf) {
431                // If it looks like a width, try to be helpful.
432                dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
433            } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
434                dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
435            } else {
436                dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
437            }
438        }
439        LitError::InvalidFloatSuffix(suffix) => {
440            let suf = suffix.as_str();
441            if looks_like_width_suffix(&['f'], suf) {
442                // If it looks like a width, try to be helpful.
443                dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
444            } else {
445                dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
446            }
447        }
448        LitError::NonDecimalFloat(base) => match base {
449            16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }),
450            8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }),
451            2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }),
452            _ => unreachable!(),
453        },
454        LitError::IntTooLarge(base) => {
455            let max = u128::MAX;
456            let limit = match base {
457                2 => format!("{max:#b}"),
458                8 => format!("{max:#o}"),
459                16 => format!("{max:#x}"),
460                _ => format!("{max}"),
461            };
462            dcx.emit_err(IntLiteralTooLarge { span, limit })
463        }
464    }
465}
466
467#[derive(Diagnostic)]
468#[diag(session_incompatible_linker_flavor)]
469#[note]
470pub(crate) struct IncompatibleLinkerFlavor {
471    pub(crate) flavor: &'static str,
472    pub(crate) compatible_list: String,
473}
474
475#[derive(Diagnostic)]
476#[diag(session_function_return_requires_x86_or_x86_64)]
477pub(crate) struct FunctionReturnRequiresX86OrX8664;
478
479#[derive(Diagnostic)]
480#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
481pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
482
483#[derive(Diagnostic)]
484#[diag(session_unsupported_regparm)]
485pub(crate) struct UnsupportedRegparm {
486    pub(crate) regparm: u32,
487}
488
489#[derive(Diagnostic)]
490#[diag(session_unsupported_regparm_arch)]
491pub(crate) struct UnsupportedRegparmArch;
492
493#[derive(Diagnostic)]
494#[diag(session_unsupported_reg_struct_return_arch)]
495pub(crate) struct UnsupportedRegStructReturnArch;
496
497#[derive(Diagnostic)]
498#[diag(session_failed_to_create_profiler)]
499pub(crate) struct FailedToCreateProfiler {
500    pub(crate) err: String,
501}
502
503#[derive(Diagnostic)]
504#[diag(session_soft_float_ignored)]
505#[note]
506pub(crate) struct SoftFloatIgnored;
507
508#[derive(Diagnostic)]
509#[diag(session_soft_float_deprecated)]
510#[note]
511#[note(session_soft_float_deprecated_issue)]
512pub(crate) struct SoftFloatDeprecated;