Skip to content

Commit 73e94f8

Browse files
committed
move some invalid exponent detection into rustc_session
1 parent ecf2d1f commit 73e94f8

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

compiler/rustc_lexer/src/lib.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pub enum DocStyle {
199199
pub enum LiteralKind {
200200
/// `12_u8`, `0o100`, `0b120i99`, `1f32`.
201201
Int { base: Base, empty_int: bool },
202-
/// `12.34f32`, `1e3`, but not `1f32`.
202+
/// `12.34f32`, `1e3` and `1e+`, but not `1f32` or `1em`.
203203
Float { base: Base, empty_exponent: bool },
204204
/// `'a'`, `'\\'`, `'''`, `';`
205205
Char { terminated: bool },
@@ -361,6 +361,17 @@ pub fn is_ident(string: &str) -> bool {
361361
}
362362
}
363363

364+
/// Is the character after the 'e' in a number valid for an exponent?
365+
///
366+
/// If not the number will be passed to the parser with a suffix beginning with 'e' rather
367+
/// than an exponent (and will be rejected there).
368+
///
369+
/// The way this function is written means that `1e_` is considered an invalid exponent
370+
/// rather than a number with suffix.
371+
fn is_exponent_second(ch: char) -> bool {
372+
matches!(ch, '0'..='9' | '_' | '+' | '-')
373+
}
374+
364375
impl Cursor<'_> {
365376
/// Parses a token from the input string.
366377
pub fn advance_token(&mut self) -> Token {
@@ -668,7 +679,7 @@ impl Cursor<'_> {
668679
if self.first().is_ascii_digit() {
669680
self.eat_decimal_digits();
670681
match self.first() {
671-
'e' | 'E' => {
682+
'e' | 'E' if is_exponent_second(self.second()) => {
672683
self.bump();
673684
empty_exponent = !self.eat_float_exponent();
674685
}
@@ -677,7 +688,7 @@ impl Cursor<'_> {
677688
}
678689
Float { base, empty_exponent }
679690
}
680-
'e' | 'E' => {
691+
'e' | 'E' if is_exponent_second(self.second()) => {
681692
self.bump();
682693
let empty_exponent = !self.eat_float_exponent();
683694
Float { base, empty_exponent }

compiler/rustc_session/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at
1818
1919
session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled
2020
21+
session_empty_float_exponent = expected at least one digit in exponent
22+
2123
session_expr_parentheses_needed = parentheses are required to parse this as an expression
2224
2325
session_failed_to_create_profiler = failed to create profiler: {$err}

compiler/rustc_session/src/errors.rs

+15
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@ pub fn report_lit_error(
397397
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
398398
}
399399

400+
fn looks_like_exponent(s: &str) -> bool {
401+
s.len() == 1 && matches!(s.chars().next(), Some('e' | 'E'))
402+
}
403+
400404
// Try to lowercase the prefix if the prefix and suffix are valid.
401405
fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
402406
let mut chars = suffix.chars();
@@ -429,6 +433,8 @@ pub fn report_lit_error(
429433
if looks_like_width_suffix(&['i', 'u'], suf) {
430434
// If it looks like a width, try to be helpful.
431435
dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
436+
} else if looks_like_exponent(suf) {
437+
dcx.emit_err(EmptyFloatExponent { span })
432438
} else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
433439
dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
434440
} else {
@@ -440,6 +446,8 @@ pub fn report_lit_error(
440446
if looks_like_width_suffix(&['f'], suf) {
441447
// If it looks like a width, try to be helpful.
442448
dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
449+
} else if looks_like_exponent(suf) {
450+
dcx.emit_err(EmptyFloatExponent { span })
443451
} else {
444452
dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
445453
}
@@ -501,3 +509,10 @@ pub(crate) struct SoftFloatIgnored;
501509
#[note]
502510
#[note(session_soft_float_deprecated_issue)]
503511
pub(crate) struct SoftFloatDeprecated;
512+
513+
#[derive(Diagnostic)]
514+
#[diag(session_empty_float_exponent)]
515+
pub(crate) struct EmptyFloatExponent {
516+
#[primary_span]
517+
pub span: Span,
518+
}

0 commit comments

Comments
 (0)