From 99c21f29bb30bfea4d61cb72477ae476840f08c1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 5 Aug 2023 19:39:51 +1000 Subject: [PATCH] Disallow leading underscores in float exponents. Such as `1e_3`, `1E+__3`, `1e-_________3_3`. - They are ugly and never used in practice. (The test suite and compiler code have no examples of them.) - They don't match normal decimal literals. (You can't write `x = _3;`.) - They complicate attempts to allow integers with suffixes beginning with `e`, such as `1em` (currently disallowed, but desired in #111615). Because when given a char sequence like `1e` the lexer must decide whether what follows the `e` is a decimal integer (in which case it's a float with exponent) or something else (in which case it's an integer with a suffix). But unbounded char lookahead is required to get past the possibly unlimited number of leading underscores. Disallowing the leading underscores reduces the lookahead to two: one for a possible `+`/`-`, and then one more for a digit or non-digit. --- compiler/rustc_lexer/src/lib.rs | 9 +- tests/ui/lexer/lex-bad-numeric-literals.rs | 12 +++ .../ui/lexer/lex-bad-numeric-literals.stderr | 88 +++++++++++++++---- 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 43dfd34a6ff74..433881354cd2c 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -869,7 +869,14 @@ impl Cursor<'_> { if self.first() == '-' || self.first() == '+' { self.bump(); } - self.eat_decimal_digits() + match self.first() { + '0'..='9' => { + self.bump(); + self.eat_decimal_digits(); + true + } + _ => false, + } } // Eats the suffix of the literal, e.g. "u8". diff --git a/tests/ui/lexer/lex-bad-numeric-literals.rs b/tests/ui/lexer/lex-bad-numeric-literals.rs index 56bdc50e40d68..7a7741cd8da0c 100644 --- a/tests/ui/lexer/lex-bad-numeric-literals.rs +++ b/tests/ui/lexer/lex-bad-numeric-literals.rs @@ -12,6 +12,18 @@ fn main() { 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported 0o; //~ ERROR: no valid digits 1e+; //~ ERROR: expected at least one digit in exponent + 1e_3; + //~^ ERROR: invalid suffix `_3` for float literal + //~| ERROR: expected at least one digit in exponent + 1E+__3; + //~^ ERROR: invalid suffix `__3` for float literal + //~| ERROR: expected at least one digit in exponent + 1e-______3_3; + //~^ ERROR: invalid suffix `______3_3` for float literal + //~| ERROR: expected at least one digit in exponent + 1em; + //~^ ERROR: invalid suffix `m` for float literal + //~| ERROR: expected at least one digit in exponent 0x539.0; //~ ERROR: hexadecimal float literal is not supported 9900000000000000000000000000999999999999999999999999999999; //~^ ERROR: integer literal is too large diff --git a/tests/ui/lexer/lex-bad-numeric-literals.stderr b/tests/ui/lexer/lex-bad-numeric-literals.stderr index 1457541970af4..7d1b03129d50c 100644 --- a/tests/ui/lexer/lex-bad-numeric-literals.stderr +++ b/tests/ui/lexer/lex-bad-numeric-literals.stderr @@ -58,50 +58,74 @@ error: expected at least one digit in exponent LL | 1e+; | ^^^ -error: hexadecimal float literal is not supported +error: expected at least one digit in exponent --> $DIR/lex-bad-numeric-literals.rs:15:5 | +LL | 1e_3; + | ^^^^ + +error: expected at least one digit in exponent + --> $DIR/lex-bad-numeric-literals.rs:18:5 + | +LL | 1E+__3; + | ^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/lex-bad-numeric-literals.rs:21:5 + | +LL | 1e-______3_3; + | ^^^^^^^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/lex-bad-numeric-literals.rs:24:5 + | +LL | 1em; + | ^^^ + +error: hexadecimal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:27:5 + | LL | 0x539.0; | ^^^^^^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:26:5 + --> $DIR/lex-bad-numeric-literals.rs:38:5 | LL | 0x; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:27:5 + --> $DIR/lex-bad-numeric-literals.rs:39:5 | LL | 0xu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:28:5 + --> $DIR/lex-bad-numeric-literals.rs:40:5 | LL | 0ou32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:29:5 + --> $DIR/lex-bad-numeric-literals.rs:41:5 | LL | 0bu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:30:5 + --> $DIR/lex-bad-numeric-literals.rs:42:5 | LL | 0b; | ^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:32:5 + --> $DIR/lex-bad-numeric-literals.rs:44:5 | LL | 0o123.456; | ^^^^^^^^^ error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:34:5 + --> $DIR/lex-bad-numeric-literals.rs:46:5 | LL | 0b111.101; | ^^^^^^^^^ @@ -112,8 +136,40 @@ error: octal float literal is not supported LL | 0o2f32; | ^^^^^^ not supported +error: invalid suffix `_3` for float literal + --> $DIR/lex-bad-numeric-literals.rs:15:5 + | +LL | 1e_3; + | ^^^^ invalid suffix `_3` + | + = help: valid suffixes are `f32` and `f64` + +error: invalid suffix `__3` for float literal + --> $DIR/lex-bad-numeric-literals.rs:18:5 + | +LL | 1E+__3; + | ^^^^^^ invalid suffix `__3` + | + = help: valid suffixes are `f32` and `f64` + +error: invalid suffix `______3_3` for float literal + --> $DIR/lex-bad-numeric-literals.rs:21:5 + | +LL | 1e-______3_3; + | ^^^^^^^^^^^^ invalid suffix `______3_3` + | + = help: valid suffixes are `f32` and `f64` + +error: invalid suffix `m` for float literal + --> $DIR/lex-bad-numeric-literals.rs:24:5 + | +LL | 1em; + | ^^^ invalid suffix `m` + | + = help: valid suffixes are `f32` and `f64` + error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:16:5 + --> $DIR/lex-bad-numeric-literals.rs:28:5 | LL | 9900000000000000000000000000999999999999999999999999999999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +177,7 @@ LL | 9900000000000000000000000000999999999999999999999999999999; = note: value exceeds limit of `340282366920938463463374607431768211455` error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:18:5 + --> $DIR/lex-bad-numeric-literals.rs:30:5 | LL | 9900000000000000000000000000999999999999999999999999999999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +185,7 @@ LL | 9900000000000000000000000000999999999999999999999999999999; = note: value exceeds limit of `340282366920938463463374607431768211455` error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:20:5 + --> $DIR/lex-bad-numeric-literals.rs:32:5 | LL | 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,7 +193,7 @@ LL | 0b111111111111111111111111111111111111111111111111111111111111111111111 = note: value exceeds limit of `0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111` error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:22:5 + --> $DIR/lex-bad-numeric-literals.rs:34:5 | LL | 0o37777777777777777777777777777777777777777770; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +201,7 @@ LL | 0o37777777777777777777777777777777777777777770; = note: value exceeds limit of `0o3777777777777777777777777777777777777777777` error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:24:5 + --> $DIR/lex-bad-numeric-literals.rs:36:5 | LL | 0xffffffffffffffffffffffffffffffff0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,17 +209,17 @@ LL | 0xffffffffffffffffffffffffffffffff0; = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:31:5 + --> $DIR/lex-bad-numeric-literals.rs:43:5 | LL | 0o123f64; | ^^^^^^^^ not supported error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:33:5 + --> $DIR/lex-bad-numeric-literals.rs:45:5 | LL | 0b101f64; | ^^^^^^^^ not supported -error: aborting due to 26 previous errors +error: aborting due to 34 previous errors For more information about this error, try `rustc --explain E0768`.