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 in fact invalid.
This commit is contained in:
Cassaundra Smith 2022-12-01 19:17:03 -08:00
parent 2585bcea0b
commit 52a9280fb2
No known key found for this signature in database
GPG Key ID: E8087B0F3D674D9B
3 changed files with 107 additions and 10 deletions

View File

@ -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.
@ -324,7 +337,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() });

View File

@ -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.)
}

View File

@ -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