diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index ee492f802a7..4266430c4c6 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -291,20 +291,33 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: 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}")) + // Try to lowercase the prefix if the prefix and suffix are valid. + fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option { + let mut chars = suffix.chars(); + + let base_char = chars.next().unwrap(); + let base = match base_char { + 'B' => 2, + 'O' => 8, + 'X' => 16, + _ => return None, + }; + + // check that the suffix contains only base-appropriate characters + let valid = prefix == "0" + && chars + .filter(|c| *c != '_') + .take_while(|c| *c != 'i' && *c != 'u') + .all(|c| c.to_digit(base).is_some()); + + if valid { + Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..])) } else { None } } - let token::Lit { kind, suffix, .. } = lit; + let token::Lit { kind, symbol, 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. @@ -320,7 +333,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: 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) { + } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) { sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); } else { sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs new file mode 100644 index 00000000000..f00cde4a74c --- /dev/null +++ b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs @@ -0,0 +1,34 @@ +// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization +// suggestions. + +fn main() { + _ = 123X1a3; + //~^ ERROR invalid suffix `X1a3` for number literal + //~| NOTE invalid suffix `X1a3` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 456O123; + //~^ ERROR invalid suffix `O123` for number literal + //~| NOTE invalid suffix `O123` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 789B101; + //~^ ERROR invalid suffix `B101` for number literal + //~| NOTE invalid suffix `B101` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0XYZ; + //~^ ERROR invalid suffix `XYZ` for number literal + //~| NOTE invalid suffix `XYZ` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0OPQ; + //~^ ERROR invalid suffix `OPQ` for number literal + //~| NOTE invalid suffix `OPQ` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0BCD; + //~^ ERROR invalid suffix `BCD` for number literal + //~| NOTE invalid suffix `BCD` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) +} diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr new file mode 100644 index 00000000000..380c16ca789 --- /dev/null +++ b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr @@ -0,0 +1,50 @@ +error: invalid suffix `X1a3` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9 + | +LL | _ = 123X1a3; + | ^^^^^^^ invalid suffix `X1a3` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `O123` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9 + | +LL | _ = 456O123; + | ^^^^^^^ invalid suffix `O123` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `B101` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9 + | +LL | _ = 789B101; + | ^^^^^^^ invalid suffix `B101` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `XYZ` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9 + | +LL | _ = 0XYZ; + | ^^^^ invalid suffix `XYZ` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `OPQ` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9 + | +LL | _ = 0OPQ; + | ^^^^ invalid suffix `OPQ` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `BCD` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9 + | +LL | _ = 0BCD; + | ^^^^ invalid suffix `BCD` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: aborting due to 6 previous errors +