X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_session%2Fsrc%2Ferrors.rs;h=4bfa583fc72bbd441fabac9bf57627e3ca4ad06c;hb=358a603f110b0489d22f3929d3f232e684fd9ffb;hp=bf542faec41d672eec81641e4a4ef5c5b1103f89;hpb=5ee0fb1c688c38a9c2649104ca28e442f0698be3;p=rust.git diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index bf542faec41..4bfa583fc72 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,6 +1,9 @@ use std::num::NonZeroU32; use crate::cgu_reuse_tracker::CguReuse; +use crate::parse::ParseSess; +use rustc_ast::token; +use rustc_ast::util::literal::LitError; use rustc_errors::MultiSpan; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -191,3 +194,162 @@ pub enum UnleashedFeatureHelp { span: Span, }, } + +#[derive(Diagnostic)] +#[diag(parser_invalid_literal_suffix)] +pub(crate) struct InvalidLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + // FIXME(#100717) + pub kind: String, + pub suffix: Symbol, +} + +#[derive(Diagnostic)] +#[diag(parser_invalid_int_literal_width)] +#[help] +pub(crate) struct InvalidIntLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(Diagnostic)] +#[diag(parser_invalid_num_literal_base_prefix)] +#[note] +pub(crate) struct InvalidNumLiteralBasePrefix { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] + pub span: Span, + pub fixed: String, +} + +#[derive(Diagnostic)] +#[diag(parser_invalid_num_literal_suffix)] +#[help] +pub(crate) struct InvalidNumLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(Diagnostic)] +#[diag(parser_invalid_float_literal_width)] +#[help] +pub(crate) struct InvalidFloatLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(Diagnostic)] +#[diag(parser_invalid_float_literal_suffix)] +#[help] +pub(crate) struct InvalidFloatLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(Diagnostic)] +#[diag(parser_int_literal_too_large)] +pub(crate) struct IntLiteralTooLarge { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser_hexadecimal_float_literal_not_supported)] +pub(crate) struct HexadecimalFloatLiteralNotSupported { + #[primary_span] + #[label(parser_not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser_octal_float_literal_not_supported)] +pub(crate) struct OctalFloatLiteralNotSupported { + #[primary_span] + #[label(parser_not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser_binary_float_literal_not_supported)] +pub(crate) struct BinaryFloatLiteralNotSupported { + #[primary_span] + #[label(parser_not_supported)] + pub span: Span, +} + +pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { + // Checks if `s` looks like i32 or u1234 etc. + fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { + s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) + } + + // Try to lowercase the prefix if it's a valid base prefix. + fn fix_base_capitalisation(s: &str) -> Option { + if let Some(stripped) = s.strip_prefix('B') { + Some(format!("0b{stripped}")) + } else if let Some(stripped) = s.strip_prefix('O') { + Some(format!("0o{stripped}")) + } else if let Some(stripped) = s.strip_prefix('X') { + Some(format!("0x{stripped}")) + } else { + None + } + } + + let token::Lit { kind, suffix, .. } = lit; + match err { + // `LexerError` is an error, but it was already reported + // by lexer, so here we don't report it the second time. + LitError::LexerError => {} + LitError::InvalidSuffix => { + if let Some(suffix) = suffix { + sess.emit_err(InvalidLiteralSuffix { + span, + kind: format!("{}", kind.descr()), + suffix, + }); + } + } + LitError::InvalidIntSuffix => { + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); + if looks_like_width_suffix(&['i', 'u'], &suf) { + // If it looks like a width, try to be helpful. + sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); + } else if let Some(fixed) = fix_base_capitalisation(suf) { + sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); + } else { + sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); + } + } + LitError::InvalidFloatSuffix => { + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); + if looks_like_width_suffix(&['f'], suf) { + // If it looks like a width, try to be helpful. + sess.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }); + } else { + sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }); + } + } + LitError::NonDecimalFloat(base) => { + match base { + 16 => sess.emit_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => sess.emit_err(OctalFloatLiteralNotSupported { span }), + 2 => sess.emit_err(BinaryFloatLiteralNotSupported { span }), + _ => unreachable!(), + }; + } + LitError::IntTooLarge => { + sess.emit_err(IntLiteralTooLarge { span }); + } + } +}