1 use std::num::NonZeroU32;
3 use crate::cgu_reuse_tracker::CguReuse;
4 use crate::parse::ParseSess;
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};
13 #[diag(session_incorrect_cgu_reuse_type)]
14 pub struct IncorrectCguReuseType<'a> {
17 pub cgu_user_name: &'a str,
18 pub actual_reuse: CguReuse,
19 pub expected_reuse: CguReuse,
24 #[diag(session_cgu_not_recorded)]
25 pub struct CguNotRecorded<'a> {
26 pub cgu_user_name: &'a str,
27 pub cgu_name: &'a str,
31 #[diag(session_feature_gate_error, code = "E0658")]
32 pub struct FeatureGateError<'a> {
38 #[derive(Subdiagnostic)]
39 #[note(session_feature_diagnostic_for_issue)]
40 pub struct FeatureDiagnosticForIssue {
44 #[derive(Subdiagnostic)]
45 #[help(session_feature_diagnostic_help)]
46 pub struct FeatureDiagnosticHelp {
51 #[diag(session_not_circumvent_feature)]
52 pub struct NotCircumventFeature;
55 #[diag(session_linker_plugin_lto_windows_not_supported)]
56 pub struct LinkerPluginToWindowsNotSupported;
59 #[diag(session_profile_use_file_does_not_exist)]
60 pub struct ProfileUseFileDoesNotExist<'a> {
61 pub path: &'a std::path::Path,
65 #[diag(session_profile_sample_use_file_does_not_exist)]
66 pub struct ProfileSampleUseFileDoesNotExist<'a> {
67 pub path: &'a std::path::Path,
71 #[diag(session_target_requires_unwind_tables)]
72 pub struct TargetRequiresUnwindTables;
75 #[diag(session_sanitizer_not_supported)]
76 pub struct SanitizerNotSupported {
81 #[diag(session_sanitizers_not_supported)]
82 pub struct SanitizersNotSupported {
87 #[diag(session_cannot_mix_and_match_sanitizers)]
88 pub struct CannotMixAndMatchSanitizers {
94 #[diag(session_cannot_enable_crt_static_linux)]
95 pub struct CannotEnableCrtStaticLinux;
98 #[diag(session_sanitizer_cfi_enabled)]
99 pub struct SanitizerCfiEnabled;
101 #[derive(Diagnostic)]
102 #[diag(session_unstable_virtual_function_elimination)]
103 pub struct UnstableVirtualFunctionElimination;
105 #[derive(Diagnostic)]
106 #[diag(session_unsupported_dwarf_version)]
107 pub struct UnsupportedDwarfVersion {
108 pub dwarf_version: u32,
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,
118 #[derive(Diagnostic)]
119 #[diag(session_split_debuginfo_unstable_platform)]
120 pub struct SplitDebugInfoUnstablePlatform {
121 pub debuginfo: SplitDebuginfo,
124 #[derive(Diagnostic)]
125 #[diag(session_file_is_not_writeable)]
126 pub struct FileIsNotWriteable<'a> {
127 pub file: &'a std::path::Path,
130 #[derive(Diagnostic)]
131 #[diag(session_crate_name_does_not_match)]
132 pub struct CrateNameDoesNotMatch<'a> {
139 #[derive(Diagnostic)]
140 #[diag(session_crate_name_invalid)]
141 pub struct CrateNameInvalid<'a> {
145 #[derive(Diagnostic)]
146 #[diag(session_crate_name_empty)]
147 pub struct CrateNameEmpty {
149 pub span: Option<Span>,
152 #[derive(Diagnostic)]
153 #[diag(session_invalid_character_in_create_name)]
154 pub struct InvalidCharacterInCrateName<'a> {
156 pub span: Option<Span>,
158 pub crate_name: &'a str,
161 #[derive(Subdiagnostic)]
162 #[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
163 pub struct ExprParenthesesNeeded {
164 #[suggestion_part(code = "(")]
166 #[suggestion_part(code = ")")]
170 impl ExprParenthesesNeeded {
171 pub fn surrounding(s: Span) -> Self {
172 ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
176 #[derive(Diagnostic)]
177 #[diag(session_skipping_const_checks)]
178 pub struct SkippingConstChecks {
179 #[subdiagnostic(eager)]
180 pub unleashed_features: Vec<UnleashedFeatureHelp>,
183 #[derive(Subdiagnostic)]
184 pub enum UnleashedFeatureHelp {
185 #[help(session_unleashed_feature_help_named)]
191 #[help(session_unleashed_feature_help_unnamed)]
198 #[derive(Diagnostic)]
199 #[diag(session_invalid_literal_suffix)]
200 pub(crate) struct InvalidLiteralSuffix {
209 #[derive(Diagnostic)]
210 #[diag(session_invalid_int_literal_width)]
212 pub(crate) struct InvalidIntLiteralWidth {
218 #[derive(Diagnostic)]
219 #[diag(session_invalid_num_literal_base_prefix)]
221 pub(crate) struct InvalidNumLiteralBasePrefix {
223 #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
228 #[derive(Diagnostic)]
229 #[diag(session_invalid_num_literal_suffix)]
231 pub(crate) struct InvalidNumLiteralSuffix {
238 #[derive(Diagnostic)]
239 #[diag(session_invalid_float_literal_width)]
241 pub(crate) struct InvalidFloatLiteralWidth {
247 #[derive(Diagnostic)]
248 #[diag(session_invalid_float_literal_suffix)]
250 pub(crate) struct InvalidFloatLiteralSuffix {
257 #[derive(Diagnostic)]
258 #[diag(session_int_literal_too_large)]
259 pub(crate) struct IntLiteralTooLarge {
264 #[derive(Diagnostic)]
265 #[diag(session_hexadecimal_float_literal_not_supported)]
266 pub(crate) struct HexadecimalFloatLiteralNotSupported {
268 #[label(session_not_supported)]
272 #[derive(Diagnostic)]
273 #[diag(session_octal_float_literal_not_supported)]
274 pub(crate) struct OctalFloatLiteralNotSupported {
276 #[label(session_not_supported)]
280 #[derive(Diagnostic)]
281 #[diag(session_binary_float_literal_not_supported)]
282 pub(crate) struct BinaryFloatLiteralNotSupported {
284 #[label(session_not_supported)]
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())
294 // Try to lowercase the prefix if it's a valid base prefix.
295 fn fix_base_capitalisation(s: &str) -> Option<String> {
296 if let Some(stripped) = s.strip_prefix('B') {
297 Some(format!("0b{stripped}"))
298 } else if let Some(stripped) = s.strip_prefix('O') {
299 Some(format!("0o{stripped}"))
300 } else if let Some(stripped) = s.strip_prefix('X') {
301 Some(format!("0x{stripped}"))
307 let token::Lit { kind, suffix, .. } = lit;
309 // `LexerError` is an error, but it was already reported
310 // by lexer, so here we don't report it the second time.
311 LitError::LexerError => {}
312 LitError::InvalidSuffix => {
313 if let Some(suffix) = suffix {
314 sess.emit_err(InvalidLiteralSuffix {
316 kind: format!("{}", kind.descr()),
321 LitError::InvalidIntSuffix => {
322 let suf = suffix.expect("suffix error with no suffix");
323 let suf = suf.as_str();
324 if looks_like_width_suffix(&['i', 'u'], &suf) {
325 // If it looks like a width, try to be helpful.
326 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
327 } else if let Some(fixed) = fix_base_capitalisation(suf) {
328 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
330 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
333 LitError::InvalidFloatSuffix => {
334 let suf = suffix.expect("suffix error with no suffix");
335 let suf = suf.as_str();
336 if looks_like_width_suffix(&['f'], suf) {
337 // If it looks like a width, try to be helpful.
338 sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
340 sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
343 LitError::NonDecimalFloat(base) => {
345 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
346 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }),
347 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }),
351 LitError::IntTooLarge => {
352 sess.emit_err(IntLiteralTooLarge { span });