Skip to content

Commit

Permalink
Rollup merge of rust-lang#105161 - cassaundra:numeric-literal-error, …
Browse files Browse the repository at this point in the history
…r=nnethercote

Refine when invalid prefix case error arises

Fix cases where the "invalid base prefix for number literal" error arises with suffixes that look erroneously capitalized but which are actually invalid.
  • Loading branch information
matthiaskrgr authored Dec 14, 2022
2 parents a270aee + 52a9280 commit 8ed0384
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 10 deletions.
33 changes: 23 additions & 10 deletions compiler/rustc_session/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> {
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<String> {
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.
Expand All @@ -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() });
Expand Down
34 changes: 34 additions & 0 deletions src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs
Original file line number Diff line number Diff line change
@@ -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.)
}
50 changes: 50 additions & 0 deletions src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8ed0384

Please sign in to comment.