Skip to content

Commit

Permalink
Move report_lit_error from rustc_session to rustc_parse.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nnethercote committed Dec 18, 2023
1 parent 25dd832 commit 90e436f
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 214 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3422,6 +3422,7 @@ dependencies = [
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_parse",
"rustc_session",
"rustc_span",
"rustc_target",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::span_bug;
use rustc_session::errors::report_lit_error;
use rustc_parse::parser::report_lit_error;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/concat.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_expand::base::{self, DummyResult};
use rustc_session::errors::report_lit_error;
use rustc_parse::parser::report_lit_error;
use rustc_span::symbol::Symbol;

use crate::errors;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/concat_bytes.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_ast::{ptr::P, tokenstream::TokenStream};
use rustc_expand::base::{self, DummyResult};
use rustc_session::errors::report_lit_error;
use rustc_parse::parser::report_lit_error;
use rustc_span::Span;

use crate::errors;
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ use rustc_errors::{
use rustc_feature::Features;
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
use rustc_parse::{parser, MACRO_ARGUMENTS};
use rustc_session::errors::report_lit_error;
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
use rustc_session::{parse::ParseSess, Limit, Session};
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
Expand Down Expand Up @@ -1251,7 +1250,7 @@ pub fn expr_to_spanned_string<'a>(
}
Ok(ast::LitKind::Err) => None,
Err(err) => {
report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span);
parser::report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span);
None
}
_ => Some((cx.struct_span_err(expr.span, err_msg), false)),
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ parse_bare_cr = {$double_quotes ->
parse_bare_cr_in_raw_string = bare CR not allowed in raw string
parse_binary_float_literal_not_supported = binary float literal is not supported
parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
parse_box_not_pat = expected pattern, found {$descr}
Expand Down Expand Up @@ -292,7 +294,11 @@ parse_generic_parameters_without_angle_brackets = generic parameters without sur
parse_generics_in_path = unexpected generic arguments in path
parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
parse_if_expression_missing_condition = missing condition for `if` expression
.condition_label = expected condition here
.block_label = if this block is the condition of the `if` expression, then it must be followed by another block
Expand Down Expand Up @@ -364,6 +370,9 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
.label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
parse_int_literal_too_large = integer literal is too large
.note = value exceeds limit of `{$limit}`
parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
.label = the `block` fragment is within this context
.suggestion = wrap this in another block
Expand All @@ -388,8 +397,18 @@ parse_invalid_dyn_keyword = invalid `dyn` keyword
.suggestion = remove this keyword
parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
.label = invalid suffix `{$suffix}`
.help = valid suffixes are `f32` and `f64`
parse_invalid_float_literal_width = invalid width `{$width}` for float literal
.help = valid widths are 32 and 64
parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
.help = valid widths are 8, 16, 32, 64 and 128
parse_invalid_interpolated_expression = invalid interpolated expression
parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
Expand All @@ -408,6 +427,14 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
.note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
.suggestion = try making the prefix lowercase
parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
.label = invalid suffix `{$suffix}`
.help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
parse_invalid_unicode_escape = invalid unicode character escape
.label = invalid escape
.help = unicode escape must {$surrogate ->
Expand Down Expand Up @@ -614,6 +641,8 @@ parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns ar
parse_nul_in_c_str = null characters in C string literals are not supported
parse_octal_float_literal_not_supported = octal float literal is not supported
parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
parse_out_of_range_hex_escape = out of range hex escape
Expand Down
92 changes: 92 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2902,3 +2902,95 @@ pub(crate) struct TransposeDynOrImplSugg<'a> {
pub insertion_span: Span,
pub kw: &'a str,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_literal_suffix)]
pub(crate) struct InvalidLiteralSuffix<'a> {
#[primary_span]
#[label]
pub span: Span,
// FIXME(#100717)
pub kind: &'a str,
pub suffix: Symbol,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_int_literal_width)]
#[help]
pub(crate) struct InvalidIntLiteralWidth {
#[primary_span]
pub span: Span,
pub width: String,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_num_literal_base_prefix)]
#[note]
pub(crate) struct InvalidNumLiteralBasePrefix {
#[primary_span]
#[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
pub span: Span,
pub fixed: String,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_num_literal_suffix)]
#[help]
pub(crate) struct InvalidNumLiteralSuffix {
#[primary_span]
#[label]
pub span: Span,
pub suffix: String,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_float_literal_width)]
#[help]
pub(crate) struct InvalidFloatLiteralWidth {
#[primary_span]
pub span: Span,
pub width: String,
}

#[derive(Diagnostic)]
#[diag(parse_invalid_float_literal_suffix)]
#[help]
pub(crate) struct InvalidFloatLiteralSuffix {
#[primary_span]
#[label]
pub span: Span,
pub suffix: String,
}

#[derive(Diagnostic)]
#[diag(parse_hexadecimal_float_literal_not_supported)]
pub(crate) struct HexadecimalFloatLiteralNotSupported {
#[primary_span]
#[label(parse_not_supported)]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_octal_float_literal_not_supported)]
pub(crate) struct OctalFloatLiteralNotSupported {
#[primary_span]
#[label(parse_not_supported)]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_binary_float_literal_not_supported)]
pub(crate) struct BinaryFloatLiteralNotSupported {
#[primary_span]
#[label(parse_not_supported)]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_int_literal_too_large)]
#[note]
pub(crate) struct IntLiteralTooLarge {
#[primary_span]
pub span: Span,
pub limit: String,
}
88 changes: 87 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::Spacing;
use rustc_ast::util::case::Case;
use rustc_ast::util::classify;
use rustc_ast::util::literal::LitError;
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
use rustc_ast::visit::Visitor;
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID};
Expand All @@ -30,9 +31,10 @@ use rustc_errors::{
PResult, StashKey,
};
use rustc_macros::Subdiagnostic;
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{self, Spanned};
use rustc_span::symbol::kw::PathRoot;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
Expand Down Expand Up @@ -3674,6 +3676,90 @@ impl<'a> Parser<'a> {
}
}

pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
// Checks if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
}

// Try to lowercase the prefix if the prefix and suffix are valid.
fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
let mut chars = suffix.chars();

let base_char = chars.next().unwrap();
let base = match base_char {
'B' => 2,
'O' => 8,
'X' => 16,
_ => return None,
};

// check that the suffix contains only base-appropriate characters
let valid = prefix == "0"
&& chars
.filter(|c| *c != '_')
.take_while(|c| *c != 'i' && *c != 'u')
.all(|c| c.to_digit(base).is_some());

valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
}

let token::Lit { kind, symbol, suffix, .. } = lit;
match err {
// `LexerError` is an error, but it was already reported
// by lexer, so here we don't report it the second time.
LitError::LexerError => {}
LitError::InvalidSuffix => {
if let Some(suffix) = suffix {
sess.emit_err(errors::InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
}
}
LitError::InvalidIntSuffix => {
let suf = suffix.expect("suffix error with no suffix");
let suf = suf.as_str();
if looks_like_width_suffix(&['i', 'u'], suf) {
// If it looks like a width, try to be helpful.
sess.emit_err(errors::InvalidIntLiteralWidth { span, width: suf[1..].into() });
} else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
sess.emit_err(errors::InvalidNumLiteralBasePrefix { span, fixed });
} else {
sess.emit_err(errors::InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
}
}
LitError::InvalidFloatSuffix => {
let suf = suffix.expect("suffix error with no suffix");
let suf = suf.as_str();
if looks_like_width_suffix(&['f'], suf) {
// If it looks like a width, try to be helpful.
sess.emit_err(errors::InvalidFloatLiteralWidth {
span,
width: suf[1..].to_string(),
});
} else {
sess.emit_err(errors::InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
}
}
LitError::NonDecimalFloat(base) => {
match base {
16 => sess.emit_err(errors::HexadecimalFloatLiteralNotSupported { span }),
8 => sess.emit_err(errors::OctalFloatLiteralNotSupported { span }),
2 => sess.emit_err(errors::BinaryFloatLiteralNotSupported { span }),
_ => unreachable!(),
};
}
LitError::IntTooLarge(base) => {
let max = u128::MAX;
let limit = match base {
2 => format!("{max:#b}"),
8 => format!("{max:#o}"),
16 => format!("{max:#x}"),
_ => format!("{max}"),
};
sess.emit_err(errors::IntLiteralTooLarge { span, limit });
}
}
}

/// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod stmt;
mod ty;

use crate::lexer::UnmatchedDelim;
pub use crate::parser::expr::report_lit_error;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
pub(crate) use expr::ForbiddenLetReason;
Expand Down
Loading

0 comments on commit 90e436f

Please sign in to comment.