Skip to content

Commit a9af5ee

Browse files
committed
move some invalid exponent detection into rustc_session
1 parent 8dac72b commit a9af5ee

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

compiler/rustc_lexer/src/lib.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ pub enum DocStyle {
194194
pub enum LiteralKind {
195195
/// `12_u8`, `0o100`, `0b120i99`, `1f32`.
196196
Int { base: Base, empty_int: bool },
197-
/// `12.34f32`, `1e3`, but not `1f32`.
197+
/// `12.34f32`, `1e3` and `1e+`, but not `1f32` or `1em`.
198198
Float { base: Base, empty_exponent: bool },
199199
/// `'a'`, `'\\'`, `'''`, `';`
200200
Char { terminated: bool },
@@ -356,6 +356,17 @@ pub fn is_ident(string: &str) -> bool {
356356
}
357357
}
358358

359+
/// Is the character after the 'e' in a number valid for an exponent?
360+
///
361+
/// If not the number will be passed to the parser with a suffix beginning with 'e' rather
362+
/// than an exponent (and will be rejected there).
363+
///
364+
/// The way this function is written means that `1e_` is considered an invalid exponent
365+
/// rather than a number with suffix.
366+
fn is_exponent_second(ch: char) -> bool {
367+
matches!(ch, '0'..='9' | '_' | '+' | '-')
368+
}
369+
359370
impl Cursor<'_> {
360371
/// Parses a token from the input string.
361372
pub fn advance_token(&mut self) -> Token {
@@ -661,7 +672,7 @@ impl Cursor<'_> {
661672
if self.first().is_ascii_digit() {
662673
self.eat_decimal_digits();
663674
match self.first() {
664-
'e' | 'E' => {
675+
'e' | 'E' if is_exponent_second(self.second()) => {
665676
self.bump();
666677
empty_exponent = !self.eat_float_exponent();
667678
}
@@ -670,7 +681,7 @@ impl Cursor<'_> {
670681
}
671682
Float { base, empty_exponent }
672683
}
673-
'e' | 'E' => {
684+
'e' | 'E' if is_exponent_second(self.second()) => {
674685
self.bump();
675686
let empty_exponent = !self.eat_float_exponent();
676687
Float { base, empty_exponent }

compiler/rustc_session/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at
1414
1515
session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled
1616
17+
session_empty_float_exponent = expected at least one digit in exponent
18+
1719
session_expr_parentheses_needed = parentheses are required to parse this as an expression
1820
1921
session_failed_to_create_profiler = failed to create profiler: {$err}

compiler/rustc_session/src/errors.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ pub fn report_lit_error(
377377
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
378378
}
379379

380+
fn looks_like_exponent(s: &str) -> bool {
381+
s.len() == 1 && matches!(s.chars().next(), Some('e' | 'E'))
382+
}
383+
380384
// Try to lowercase the prefix if the prefix and suffix are valid.
381385
fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
382386
let mut chars = suffix.chars();
@@ -409,6 +413,8 @@ pub fn report_lit_error(
409413
if looks_like_width_suffix(&['i', 'u'], suf) {
410414
// If it looks like a width, try to be helpful.
411415
dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
416+
} else if looks_like_exponent(suf) {
417+
dcx.emit_err(EmptyFloatExponent { span })
412418
} else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
413419
dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
414420
} else {
@@ -420,6 +426,8 @@ pub fn report_lit_error(
420426
if looks_like_width_suffix(&['f'], suf) {
421427
// If it looks like a width, try to be helpful.
422428
dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
429+
} else if looks_like_exponent(suf) {
430+
dcx.emit_err(EmptyFloatExponent { span })
423431
} else {
424432
dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
425433
}
@@ -489,3 +497,10 @@ pub(crate) struct SoftFloatIgnored;
489497
#[note]
490498
#[note(session_soft_float_deprecated_issue)]
491499
pub(crate) struct SoftFloatDeprecated;
500+
501+
#[derive(Diagnostic)]
502+
#[diag(session_empty_float_exponent)]
503+
pub(crate) struct EmptyFloatExponent {
504+
#[primary_span]
505+
pub span: Span,
506+
}

0 commit comments

Comments
 (0)