Skip to content

Commit 52a9280

Browse files
committed
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.
1 parent 2585bce commit 52a9280

File tree

3 files changed

+107
-10
lines changed

3 files changed

+107
-10
lines changed

compiler/rustc_session/src/errors.rs

+23-10
Original file line numberDiff line numberDiff line change
@@ -291,20 +291,33 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
291291
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
292292
}
293293

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}"))
294+
// Try to lowercase the prefix if the prefix and suffix are valid.
295+
fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
296+
let mut chars = suffix.chars();
297+
298+
let base_char = chars.next().unwrap();
299+
let base = match base_char {
300+
'B' => 2,
301+
'O' => 8,
302+
'X' => 16,
303+
_ => return None,
304+
};
305+
306+
// check that the suffix contains only base-appropriate characters
307+
let valid = prefix == "0"
308+
&& chars
309+
.filter(|c| *c != '_')
310+
.take_while(|c| *c != 'i' && *c != 'u')
311+
.all(|c| c.to_digit(base).is_some());
312+
313+
if valid {
314+
Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
302315
} else {
303316
None
304317
}
305318
}
306319

307-
let token::Lit { kind, suffix, .. } = lit;
320+
let token::Lit { kind, symbol, suffix, .. } = lit;
308321
match err {
309322
// `LexerError` is an error, but it was already reported
310323
// 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:
324337
if looks_like_width_suffix(&['i', 'u'], &suf) {
325338
// If it looks like a width, try to be helpful.
326339
sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
327-
} else if let Some(fixed) = fix_base_capitalisation(suf) {
340+
} else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
328341
sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
329342
} else {
330343
sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization
2+
// suggestions.
3+
4+
fn main() {
5+
_ = 123X1a3;
6+
//~^ ERROR invalid suffix `X1a3` for number literal
7+
//~| NOTE invalid suffix `X1a3`
8+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
9+
10+
_ = 456O123;
11+
//~^ ERROR invalid suffix `O123` for number literal
12+
//~| NOTE invalid suffix `O123`
13+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
14+
15+
_ = 789B101;
16+
//~^ ERROR invalid suffix `B101` for number literal
17+
//~| NOTE invalid suffix `B101`
18+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
19+
20+
_ = 0XYZ;
21+
//~^ ERROR invalid suffix `XYZ` for number literal
22+
//~| NOTE invalid suffix `XYZ`
23+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
24+
25+
_ = 0OPQ;
26+
//~^ ERROR invalid suffix `OPQ` for number literal
27+
//~| NOTE invalid suffix `OPQ`
28+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
29+
30+
_ = 0BCD;
31+
//~^ ERROR invalid suffix `BCD` for number literal
32+
//~| NOTE invalid suffix `BCD`
33+
//~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: invalid suffix `X1a3` for number literal
2+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9
3+
|
4+
LL | _ = 123X1a3;
5+
| ^^^^^^^ invalid suffix `X1a3`
6+
|
7+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
8+
9+
error: invalid suffix `O123` for number literal
10+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9
11+
|
12+
LL | _ = 456O123;
13+
| ^^^^^^^ invalid suffix `O123`
14+
|
15+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
16+
17+
error: invalid suffix `B101` for number literal
18+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9
19+
|
20+
LL | _ = 789B101;
21+
| ^^^^^^^ invalid suffix `B101`
22+
|
23+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
24+
25+
error: invalid suffix `XYZ` for number literal
26+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9
27+
|
28+
LL | _ = 0XYZ;
29+
| ^^^^ invalid suffix `XYZ`
30+
|
31+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
32+
33+
error: invalid suffix `OPQ` for number literal
34+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9
35+
|
36+
LL | _ = 0OPQ;
37+
| ^^^^ invalid suffix `OPQ`
38+
|
39+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
40+
41+
error: invalid suffix `BCD` for number literal
42+
--> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9
43+
|
44+
LL | _ = 0BCD;
45+
| ^^^^ invalid suffix `BCD`
46+
|
47+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
48+
49+
error: aborting due to 6 previous errors
50+

0 commit comments

Comments
 (0)