Skip to content

Commit b810472

Browse files
committed
Move report_lit_error from rustc_session to rustc_parse.
It's a more logical spot for it, and will be a big help for the next commit. Doing this creates a new dependency from `rustc_ast_lowering` on `rustc_parse`, but `rustc_ast_lowering` is clearly higher up the crate graph, so this isn't a big deal. One thing in favour of this change, is that two fluent labels were duplicated across `rustc_session` and `rustc_parse`: `invalid_literal_suffix` and `parse_not_supported`. This duplication is now gone, so that's nice evidence that this is a reasonable change.
1 parent 8e37b75 commit b810472

File tree

12 files changed

+215
-212
lines changed

12 files changed

+215
-212
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3461,6 +3461,7 @@ dependencies = [
34613461
"rustc_index",
34623462
"rustc_macros",
34633463
"rustc_middle",
3464+
"rustc_parse",
34643465
"rustc_session",
34653466
"rustc_span",
34663467
"rustc_target",

compiler/rustc_ast_lowering/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rustc_hir = { path = "../rustc_hir" }
1717
rustc_index = { path = "../rustc_index" }
1818
rustc_macros = { path = "../rustc_macros" }
1919
rustc_middle = { path = "../rustc_middle" }
20+
rustc_parse = { path = "../rustc_parse" }
2021
rustc_session = { path = "../rustc_session" }
2122
rustc_span = { path = "../rustc_span" }
2223
rustc_target = { path = "../rustc_target" }

compiler/rustc_ast_lowering/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_ast::*;
1313
use rustc_data_structures::stack::ensure_sufficient_stack;
1414
use rustc_hir as hir;
1515
use rustc_hir::def::{DefKind, Res};
16-
use rustc_session::errors::report_lit_error;
16+
use rustc_parse::parser::report_lit_error;
1717
use rustc_span::source_map::{respan, Spanned};
1818
use rustc_span::symbol::{kw, sym, Ident, Symbol};
1919
use rustc_span::DUMMY_SP;

compiler/rustc_builtin_macros/src/concat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::tokenstream::TokenStream;
33
use rustc_expand::base::{self, DummyResult};
4-
use rustc_session::errors::report_lit_error;
4+
use rustc_parse::parser::report_lit_error;
55
use rustc_span::symbol::Symbol;
66

77
use crate::errors;

compiler/rustc_builtin_macros/src/concat_bytes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::{ptr::P, tokenstream::TokenStream};
33
use rustc_expand::base::{self, DummyResult};
4-
use rustc_session::errors::report_lit_error;
4+
use rustc_parse::parser::report_lit_error;
55
use rustc_span::Span;
66

77
use crate::errors;

compiler/rustc_expand/src/base.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use rustc_feature::Features;
2222
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
2323
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
2424
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
25-
use rustc_session::errors::report_lit_error;
2625
use rustc_session::{parse::ParseSess, Limit, Session};
2726
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
2827
use rustc_span::edition::Edition;
@@ -1251,7 +1250,7 @@ pub fn expr_to_spanned_string<'a>(
12511250
}
12521251
Ok(ast::LitKind::Err) => None,
12531252
Err(err) => {
1254-
report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span);
1253+
parser::report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span);
12551254
None
12561255
}
12571256
_ => Some((cx.struct_span_err(expr.span, err_msg), false)),

compiler/rustc_parse/messages.ftl

+29
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ parse_bare_cr = {$double_quotes ->
6161
6262
parse_bare_cr_in_raw_string = bare CR not allowed in raw string
6363
64+
parse_binary_float_literal_not_supported = binary float literal is not supported
65+
6466
parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
6567
6668
parse_box_not_pat = expected pattern, found {$descr}
@@ -294,7 +296,11 @@ parse_generic_parameters_without_angle_brackets = generic parameters without sur
294296
parse_generics_in_path = unexpected generic arguments in path
295297
296298
parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
299+
297300
parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
301+
302+
parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
303+
298304
parse_if_expression_missing_condition = missing condition for `if` expression
299305
.condition_label = expected condition here
300306
.block_label = if this block is the condition of the `if` expression, then it must be followed by another block
@@ -366,6 +372,9 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
366372
.label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
367373
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
368374
375+
parse_int_literal_too_large = integer literal is too large
376+
.note = value exceeds limit of `{$limit}`
377+
369378
parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
370379
.label = the `block` fragment is within this context
371380
.suggestion = wrap this in another block
@@ -390,8 +399,18 @@ parse_invalid_dyn_keyword = invalid `dyn` keyword
390399
.suggestion = remove this keyword
391400
392401
parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
402+
parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
403+
.label = invalid suffix `{$suffix}`
404+
.help = valid suffixes are `f32` and `f64`
405+
406+
parse_invalid_float_literal_width = invalid width `{$width}` for float literal
407+
.help = valid widths are 32 and 64
408+
393409
parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
394410
411+
parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
412+
.help = valid widths are 8, 16, 32, 64 and 128
413+
395414
parse_invalid_interpolated_expression = invalid interpolated expression
396415
397416
parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
@@ -410,6 +429,14 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
410429
411430
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
412431
432+
parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
433+
.note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
434+
.suggestion = try making the prefix lowercase
435+
436+
parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
437+
.label = invalid suffix `{$suffix}`
438+
.help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
439+
413440
parse_invalid_unicode_escape = invalid unicode character escape
414441
.label = invalid escape
415442
.help = unicode escape must {$surrogate ->
@@ -618,6 +645,8 @@ parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns ar
618645
619646
parse_nul_in_c_str = null characters in C string literals are not supported
620647
648+
parse_octal_float_literal_not_supported = octal float literal is not supported
649+
621650
parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
622651
parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
623652
parse_out_of_range_hex_escape = out of range hex escape

compiler/rustc_parse/src/errors.rs

+92
Original file line numberDiff line numberDiff line change
@@ -2909,3 +2909,95 @@ pub(crate) struct TransposeDynOrImplSugg<'a> {
29092909
pub insertion_span: Span,
29102910
pub kw: &'a str,
29112911
}
2912+
2913+
#[derive(Diagnostic)]
2914+
#[diag(parse_invalid_literal_suffix)]
2915+
pub(crate) struct InvalidLiteralSuffix<'a> {
2916+
#[primary_span]
2917+
#[label]
2918+
pub span: Span,
2919+
// FIXME(#100717)
2920+
pub kind: &'a str,
2921+
pub suffix: Symbol,
2922+
}
2923+
2924+
#[derive(Diagnostic)]
2925+
#[diag(parse_invalid_int_literal_width)]
2926+
#[help]
2927+
pub(crate) struct InvalidIntLiteralWidth {
2928+
#[primary_span]
2929+
pub span: Span,
2930+
pub width: String,
2931+
}
2932+
2933+
#[derive(Diagnostic)]
2934+
#[diag(parse_invalid_num_literal_base_prefix)]
2935+
#[note]
2936+
pub(crate) struct InvalidNumLiteralBasePrefix {
2937+
#[primary_span]
2938+
#[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
2939+
pub span: Span,
2940+
pub fixed: String,
2941+
}
2942+
2943+
#[derive(Diagnostic)]
2944+
#[diag(parse_invalid_num_literal_suffix)]
2945+
#[help]
2946+
pub(crate) struct InvalidNumLiteralSuffix {
2947+
#[primary_span]
2948+
#[label]
2949+
pub span: Span,
2950+
pub suffix: String,
2951+
}
2952+
2953+
#[derive(Diagnostic)]
2954+
#[diag(parse_invalid_float_literal_width)]
2955+
#[help]
2956+
pub(crate) struct InvalidFloatLiteralWidth {
2957+
#[primary_span]
2958+
pub span: Span,
2959+
pub width: String,
2960+
}
2961+
2962+
#[derive(Diagnostic)]
2963+
#[diag(parse_invalid_float_literal_suffix)]
2964+
#[help]
2965+
pub(crate) struct InvalidFloatLiteralSuffix {
2966+
#[primary_span]
2967+
#[label]
2968+
pub span: Span,
2969+
pub suffix: String,
2970+
}
2971+
2972+
#[derive(Diagnostic)]
2973+
#[diag(parse_hexadecimal_float_literal_not_supported)]
2974+
pub(crate) struct HexadecimalFloatLiteralNotSupported {
2975+
#[primary_span]
2976+
#[label(parse_not_supported)]
2977+
pub span: Span,
2978+
}
2979+
2980+
#[derive(Diagnostic)]
2981+
#[diag(parse_octal_float_literal_not_supported)]
2982+
pub(crate) struct OctalFloatLiteralNotSupported {
2983+
#[primary_span]
2984+
#[label(parse_not_supported)]
2985+
pub span: Span,
2986+
}
2987+
2988+
#[derive(Diagnostic)]
2989+
#[diag(parse_binary_float_literal_not_supported)]
2990+
pub(crate) struct BinaryFloatLiteralNotSupported {
2991+
#[primary_span]
2992+
#[label(parse_not_supported)]
2993+
pub span: Span,
2994+
}
2995+
2996+
#[derive(Diagnostic)]
2997+
#[diag(parse_int_literal_too_large)]
2998+
#[note]
2999+
pub(crate) struct IntLiteralTooLarge {
3000+
#[primary_span]
3001+
pub span: Span,
3002+
pub limit: String,
3003+
}

compiler/rustc_parse/src/parser/expr.rs

+87-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_ast::token::{self, Delimiter, Token, TokenKind};
1717
use rustc_ast::tokenstream::Spacing;
1818
use rustc_ast::util::case::Case;
1919
use rustc_ast::util::classify;
20+
use rustc_ast::util::literal::LitError;
2021
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
2122
use rustc_ast::visit::Visitor;
2223
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID};
@@ -30,9 +31,10 @@ use rustc_errors::{
3031
PResult, StashKey,
3132
};
3233
use rustc_macros::Subdiagnostic;
33-
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
34+
use rustc_session::errors::ExprParenthesesNeeded;
3435
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
3536
use rustc_session::lint::BuiltinLintDiagnostics;
37+
use rustc_session::parse::ParseSess;
3638
use rustc_span::source_map::{self, Spanned};
3739
use rustc_span::symbol::kw::PathRoot;
3840
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -3616,6 +3618,90 @@ impl<'a> Parser<'a> {
36163618
}
36173619
}
36183620

3621+
pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
3622+
// Checks if `s` looks like i32 or u1234 etc.
3623+
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
3624+
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
3625+
}
3626+
3627+
// Try to lowercase the prefix if the prefix and suffix are valid.
3628+
fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
3629+
let mut chars = suffix.chars();
3630+
3631+
let base_char = chars.next().unwrap();
3632+
let base = match base_char {
3633+
'B' => 2,
3634+
'O' => 8,
3635+
'X' => 16,
3636+
_ => return None,
3637+
};
3638+
3639+
// check that the suffix contains only base-appropriate characters
3640+
let valid = prefix == "0"
3641+
&& chars
3642+
.filter(|c| *c != '_')
3643+
.take_while(|c| *c != 'i' && *c != 'u')
3644+
.all(|c| c.to_digit(base).is_some());
3645+
3646+
valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
3647+
}
3648+
3649+
let token::Lit { kind, symbol, suffix, .. } = lit;
3650+
match err {
3651+
// `LexerError` is an error, but it was already reported
3652+
// by lexer, so here we don't report it the second time.
3653+
LitError::LexerError => {}
3654+
LitError::InvalidSuffix => {
3655+
if let Some(suffix) = suffix {
3656+
sess.emit_err(errors::InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
3657+
}
3658+
}
3659+
LitError::InvalidIntSuffix => {
3660+
let suf = suffix.expect("suffix error with no suffix");
3661+
let suf = suf.as_str();
3662+
if looks_like_width_suffix(&['i', 'u'], suf) {
3663+
// If it looks like a width, try to be helpful.
3664+
sess.emit_err(errors::InvalidIntLiteralWidth { span, width: suf[1..].into() });
3665+
} else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
3666+
sess.emit_err(errors::InvalidNumLiteralBasePrefix { span, fixed });
3667+
} else {
3668+
sess.emit_err(errors::InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
3669+
}
3670+
}
3671+
LitError::InvalidFloatSuffix => {
3672+
let suf = suffix.expect("suffix error with no suffix");
3673+
let suf = suf.as_str();
3674+
if looks_like_width_suffix(&['f'], suf) {
3675+
// If it looks like a width, try to be helpful.
3676+
sess.emit_err(errors::InvalidFloatLiteralWidth {
3677+
span,
3678+
width: suf[1..].to_string(),
3679+
});
3680+
} else {
3681+
sess.emit_err(errors::InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
3682+
}
3683+
}
3684+
LitError::NonDecimalFloat(base) => {
3685+
match base {
3686+
16 => sess.emit_err(errors::HexadecimalFloatLiteralNotSupported { span }),
3687+
8 => sess.emit_err(errors::OctalFloatLiteralNotSupported { span }),
3688+
2 => sess.emit_err(errors::BinaryFloatLiteralNotSupported { span }),
3689+
_ => unreachable!(),
3690+
};
3691+
}
3692+
LitError::IntTooLarge(base) => {
3693+
let max = u128::MAX;
3694+
let limit = match base {
3695+
2 => format!("{max:#b}"),
3696+
8 => format!("{max:#o}"),
3697+
16 => format!("{max:#x}"),
3698+
_ => format!("{max}"),
3699+
};
3700+
sess.emit_err(errors::IntLiteralTooLarge { span, limit });
3701+
}
3702+
}
3703+
}
3704+
36193705
/// Used to forbid `let` expressions in certain syntactic locations.
36203706
#[derive(Clone, Copy, Subdiagnostic)]
36213707
pub(crate) enum ForbiddenLetReason {

compiler/rustc_parse/src/parser/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod stmt;
1111
mod ty;
1212

1313
use crate::lexer::UnmatchedDelim;
14+
pub use crate::parser::expr::report_lit_error;
1415
pub use attr_wrapper::AttrWrapper;
1516
pub use diagnostics::AttemptLocalParseRecovery;
1617
pub(crate) use expr::ForbiddenLetReason;

0 commit comments

Comments
 (0)