rustc_session/
errors.rs

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