diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 098e2606a3b..b74938621b3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1846,7 +1846,7 @@ pub enum LitKind { /// A boolean literal (`true`, `false`). Bool(bool), /// Placeholder for a literal that wasn't well-formed in some way. - Err, + Err(ErrorGuaranteed), } impl LitKind { @@ -1893,7 +1893,7 @@ impl LitKind { | LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) | LitKind::Bool(..) - | LitKind::Err => false, + | LitKind::Err(_) => false, } } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d62462b1ae3..50fe37dcdb6 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -13,7 +13,7 @@ use rustc_macros::HashStable_Generic; use rustc_span::symbol::{kw, sym}; #[allow(hidden_glob_reexports)] use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{edition::Edition, Span, DUMMY_SP}; +use rustc_span::{edition::Edition, ErrorGuaranteed, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; @@ -75,7 +75,7 @@ pub enum LitKind { ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols CStr, CStrRaw(u8), - Err, + Err(ErrorGuaranteed), } /// A literal token. @@ -144,7 +144,7 @@ impl fmt::Display for Lit { CStrRaw(n) => { write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))? } - Integer | Float | Bool | Err => write!(f, "{symbol}")?, + Integer | Float | Bool | Err(_) => write!(f, "{symbol}")?, } if let Some(suffix) = suffix { @@ -159,7 +159,7 @@ impl LitKind { /// An English article for the literal token kind. pub fn article(self) -> &'static str { match self { - Integer | Err => "an", + Integer | Err(_) => "an", _ => "a", } } @@ -174,12 +174,12 @@ impl LitKind { Str | StrRaw(..) => "string", ByteStr | ByteStrRaw(..) => "byte string", CStr | CStrRaw(..) => "C string", - Err => "error", + Err(_) => "error", } } pub(crate) fn may_have_suffix(self) -> bool { - matches!(self, Integer | Float | Err) + matches!(self, Integer | Float | Err(_)) } } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index aaeb1bb9bff..5ed2762b726 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -31,20 +31,21 @@ pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol { #[derive(Debug)] pub enum LitError { - LexerError, - InvalidSuffix, - InvalidIntSuffix, - InvalidFloatSuffix, - NonDecimalFloat(u32), - IntTooLarge(u32), + InvalidSuffix(Symbol), + InvalidIntSuffix(Symbol), + InvalidFloatSuffix(Symbol), + NonDecimalFloat(u32), // u32 is the base + IntTooLarge(u32), // u32 is the base } impl LitKind { /// Converts literal token into a semantic literal. pub fn from_token_lit(lit: token::Lit) -> Result { let token::Lit { kind, symbol, suffix } = lit; - if suffix.is_some() && !kind.may_have_suffix() { - return Err(LitError::InvalidSuffix); + if let Some(suffix) = suffix + && !kind.may_have_suffix() + { + return Err(LitError::InvalidSuffix(suffix)); } // For byte/char/string literals, chars and escapes have already been @@ -145,7 +146,7 @@ impl LitKind { buf.push(0); LitKind::CStr(buf.into(), StrStyle::Raw(n)) } - token::Err => LitKind::Err, + token::Err(guar) => LitKind::Err(guar), }) } } @@ -202,7 +203,7 @@ impl fmt::Display for LitKind { } } LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?, - LitKind::Err => { + LitKind::Err(_) => { // This only shows up in places like `-Zunpretty=hir` output, so we // don't bother to produce something useful. write!(f, "")?; @@ -238,7 +239,7 @@ impl MetaItemLit { LitKind::Char(_) => token::Char, LitKind::Int(..) => token::Integer, LitKind::Float(..) => token::Float, - LitKind::Err => token::Err, + LitKind::Err(guar) => token::Err(guar), }; token::Lit::new(kind, self.symbol, self.suffix) @@ -272,12 +273,12 @@ fn filtered_float_lit( return Err(LitError::NonDecimalFloat(base)); } Ok(match suffix { - Some(suf) => LitKind::Float( + Some(suffix) => LitKind::Float( symbol, - ast::LitFloatType::Suffixed(match suf { + ast::LitFloatType::Suffixed(match suffix { sym::f32 => ast::FloatTy::F32, sym::f64 => ast::FloatTy::F64, - _ => return Err(LitError::InvalidFloatSuffix), + _ => return Err(LitError::InvalidFloatSuffix(suffix)), }), ), None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed), @@ -318,17 +319,13 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result return filtered_float_lit(symbol, suffix, base), - _ => return Err(LitError::InvalidIntSuffix), + _ => return Err(LitError::InvalidIntSuffix(suf)), }, _ => ast::LitIntType::Unsuffixed, }; let s = &s[if base != 10 { 2 } else { 0 }..]; - u128::from_str_radix(s, base).map(|i| LitKind::Int(i.into(), ty)).map_err(|_| { - // Small bases are lexed as if they were base 10, e.g, the string - // might be `0b10201`. This will cause the conversion above to fail, - // but these kinds of errors are already reported by the lexer. - let from_lexer = base < 10 && s.chars().any(|c| c.to_digit(10).is_some_and(|d| d >= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } - }) + u128::from_str_radix(s, base) + .map(|i| LitKind::Int(i.into(), ty)) + .map_err(|_| LitError::IntTooLarge(base)) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 942aae3d536..aafa99b3aa6 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -124,8 +124,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let lit_kind = match LitKind::from_token_lit(*token_lit) { Ok(lit_kind) => lit_kind, Err(err) => { - report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span); - LitKind::Err + let guar = report_lit_error( + &self.tcx.sess.parse_sess, + err, + *token_lit, + e.span, + ); + LitKind::Err(guar) } }; let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6b5fc014240..eab1383b635 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -966,10 +966,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { { lit } else { + let guar = self.dcx().has_errors().unwrap(); MetaItemLit { symbol: kw::Empty, suffix: None, - kind: LitKind::Err, + kind: LitKind::Err(guar), span: DUMMY_SP, } }; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cda746894e8..2765b235f99 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -254,7 +254,7 @@ fn literal_to_string(lit: token::Lit) -> String { token::CStrRaw(n) => { format!("cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize)) } - token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(), + token::Integer | token::Float | token::Bool | token::Err(_) => symbol.to_string(), }; if let Some(suffix) = suffix { diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index dade29593af..795161e65d8 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -40,7 +40,7 @@ pub fn expand_concat( cx.dcx().emit_err(errors::ConcatBytestr { span: e.span }); has_errors = true; } - Ok(ast::LitKind::Err) => { + Ok(ast::LitKind::Err(_)) => { has_errors = true; } Err(err) => { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index a01bbeac824..3ef8cb7bffe 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -44,7 +44,7 @@ fn invalid_type_err( Ok(ast::LitKind::Bool(_)) => { dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None }); } - Ok(ast::LitKind::Err) => {} + Ok(ast::LitKind::Err(_)) => {} Ok(ast::LitKind::Int(_, _)) if !is_nested => { let sugg = snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet }); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index cfeb31fc4c8..09ab26421d6 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1266,7 +1266,7 @@ pub fn expr_to_spanned_string<'a>( ); Some((err, true)) } - Ok(ast::LitKind::Err) => None, + Ok(ast::LitKind::Err(_)) => None, Err(err) => { report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span); None diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 3a78bd94505..8f31b5801da 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -10,7 +10,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{MultiSpan, PResult}; +use rustc_errors::{ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; @@ -63,7 +63,12 @@ impl FromInternal for LitKind { token::ByteStrRaw(n) => LitKind::ByteStrRaw(n), token::CStr => LitKind::CStr, token::CStrRaw(n) => LitKind::CStrRaw(n), - token::Err => LitKind::Err, + token::Err(_guar) => { + // This is the only place a `pm::bridge::LitKind::ErrWithGuar` + // is constructed. Note that an `ErrorGuaranteed` is available, + // as required. See the comment in `to_internal`. + LitKind::ErrWithGuar + } token::Bool => unreachable!(), } } @@ -82,7 +87,16 @@ impl ToInternal for LitKind { LitKind::ByteStrRaw(n) => token::ByteStrRaw(n), LitKind::CStr => token::CStr, LitKind::CStrRaw(n) => token::CStrRaw(n), - LitKind::Err => token::Err, + LitKind::ErrWithGuar => { + // This is annoying but valid. `LitKind::ErrWithGuar` would + // have an `ErrorGuaranteed` except that type isn't available + // in that crate. So we have to fake one. And we don't want to + // use a delayed bug because there might be lots of these, + // which would be expensive. + #[allow(deprecated)] + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + token::Err(guar) + } } } } @@ -477,7 +491,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { | token::LitKind::ByteStrRaw(_) | token::LitKind::CStr | token::LitKind::CStrRaw(_) - | token::LitKind::Err => return Err(()), + | token::LitKind::Err(_) => return Err(()), token::LitKind::Integer | token::LitKind::Float => {} } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 65b8505c090..3bce8a1dd45 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1319,7 +1319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span))) .skip_binder(), ), - ast::LitKind::Err => Ty::new_misc_error(tcx), + ast::LitKind::Err(guar) => Ty::new_error(tcx, guar), } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 6636f75d998..7c3d2671d59 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -164,11 +164,7 @@ fn lit_to_mir_constant<'tcx>( })?, (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), - (ast::LitKind::Err, _) => { - return Err(LitToConstError::Reported( - tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"), - )); - } + (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)), _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 71aebd13003..d444de8b28e 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -71,11 +71,7 @@ pub(crate) fn lit_to_const<'tcx>( ty::ValTree::from_scalar_int(bits) } (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), - (ast::LitKind::Err, _) => { - return Err(LitToConstError::Reported( - tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"), - )); - } + (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)), _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 99952e1c178..62762168cf4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -897,12 +897,14 @@ impl<'tcx> Cx<'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local()); let generics = self.tcx.generics_of(hir_id.owner); let Some(&index) = generics.param_def_id_to_index.get(&def_id) else { - self.tcx.dcx().has_errors().unwrap(); + let guar = self.tcx.dcx().has_errors().unwrap(); // We already errored about a late bound const - return ExprKind::Literal { - lit: &Spanned { span: DUMMY_SP, node: LitKind::Err }, - neg: false, - }; + + let lit = self + .tcx + .hir_arena + .alloc(Spanned { span: DUMMY_SP, node: LitKind::Err(guar) }); + return ExprKind::Literal { lit, neg: false }; }; let name = self.tcx.hir().name(hir_id); let param = ty::ParamConst::new(index, name); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 31552452676..c768ea93b5f 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -16,7 +16,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::{edition::Edition, BytePos, Pos, Span}; mod diagnostics; @@ -478,26 +478,27 @@ impl<'sess, 'src> StringReader<'sess, 'src> { } } rustc_lexer::LiteralKind::Int { base, empty_int } => { + let mut kind = token::Integer; if empty_int { let span = self.mk_sp(start, end); - self.dcx().emit_err(errors::NoDigitsLiteral { span }); - (token::Integer, sym::integer(0)) - } else { - if matches!(base, Base::Binary | Base::Octal) { - let base = base as u32; - let s = self.str_from_to(start + BytePos(2), end); - for (idx, c) in s.char_indices() { - let span = self.mk_sp( - start + BytePos::from_usize(2 + idx), - start + BytePos::from_usize(2 + idx + c.len_utf8()), - ); - if c != '_' && c.to_digit(base).is_none() { + let guar = self.dcx().emit_err(errors::NoDigitsLiteral { span }); + kind = token::Err(guar); + } else if matches!(base, Base::Binary | Base::Octal) { + let base = base as u32; + let s = self.str_from_to(start + BytePos(2), end); + for (idx, c) in s.char_indices() { + let span = self.mk_sp( + start + BytePos::from_usize(2 + idx), + start + BytePos::from_usize(2 + idx + c.len_utf8()), + ); + if c != '_' && c.to_digit(base).is_none() { + let guar = self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); - } + kind = token::Err(guar); } } - (token::Integer, self.symbol_from_to(start, end)) } + (kind, self.symbol_from_to(start, end)) } rustc_lexer::LiteralKind::Float { base, empty_exponent } => { if empty_exponent { @@ -691,7 +692,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { fn cook_common( &self, - kind: token::LitKind, + mut kind: token::LitKind, mode: Mode, start: BytePos, end: BytePos, @@ -699,7 +700,6 @@ impl<'sess, 'src> StringReader<'sess, 'src> { postfix_len: u32, unescape: fn(&str, Mode, &mut dyn FnMut(Range, Result<(), EscapeError>)), ) -> (token::LitKind, Symbol) { - let mut has_fatal_err = false; let content_start = start + BytePos(prefix_len); let content_end = end - BytePos(postfix_len); let lit_content = self.str_from_to(content_start, content_end); @@ -711,10 +711,8 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let lo = content_start + BytePos(start); let hi = lo + BytePos(end - start); let span = self.mk_sp(lo, hi); - if err.is_fatal() { - has_fatal_err = true; - } - emit_unescape_error( + let is_fatal = err.is_fatal(); + if let Some(guar) = emit_unescape_error( self.dcx(), lit_content, span_with_quotes, @@ -722,17 +720,21 @@ impl<'sess, 'src> StringReader<'sess, 'src> { mode, range, err, - ); + ) { + assert!(is_fatal); + kind = token::Err(guar); + } } }); // We normally exclude the quotes for the symbol, but for errors we // include it because it results in clearer error messages. - if !has_fatal_err { - (kind, Symbol::intern(lit_content)) + let sym = if !matches!(kind, token::Err(_)) { + Symbol::intern(lit_content) } else { - (token::Err, self.symbol_from_to(start, end)) - } + self.symbol_from_to(start, end) + }; + (kind, sym) } fn cook_unicode( diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 3238f8e23bb..3ebad6a9fd7 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, DiagCtxt}; +use rustc_errors::{Applicability, DiagCtxt, ErrorGuaranteed}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -21,7 +21,7 @@ pub(crate) fn emit_unescape_error( // range of the error inside `lit` range: Range, error: EscapeError, -) { +) -> Option { debug!( "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}", lit, full_lit_span, mode, range, error @@ -31,12 +31,12 @@ pub(crate) fn emit_unescape_error( let span = err_span.with_lo(err_span.hi() - BytePos(c.len_utf8() as u32)); (c, span) }; - match error { + Some(match error { EscapeError::LoneSurrogateUnicodeEscape => { - dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }) } EscapeError::OutOfRangeUnicodeEscape => { - dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }) } EscapeError::MoreThanOneChar => { use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; @@ -106,7 +106,7 @@ pub(crate) fn emit_unescape_error( span: full_lit_span, note, suggestion: sugg, - }); + }) } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); @@ -116,15 +116,15 @@ pub(crate) fn emit_unescape_error( escaped_sugg: c.escape_default().to_string(), escaped_msg: escaped_char(c), byte: mode == Mode::Byte, - }); + }) } EscapeError::BareCarriageReturn => { let double_quotes = mode.in_double_quotes(); - dcx.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }); + dcx.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }) } EscapeError::BareCarriageReturnInRawString => { assert!(mode.in_double_quotes()); - dcx.emit_err(UnescapeError::BareCrRawString(err_span)); + dcx.emit_err(UnescapeError::BareCrRawString(err_span)) } EscapeError::InvalidEscape => { let (c, span) = last_char(); @@ -161,16 +161,14 @@ pub(crate) fn emit_unescape_error( ", ); } - diag.emit(); - } - EscapeError::TooShortHexEscape => { - dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)); + diag.emit() } + EscapeError::TooShortHexEscape => dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)), EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { let (c, span) = last_char(); let is_hex = error == EscapeError::InvalidCharInHexEscape; let ch = escaped_char(c); - dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }); + dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }) } EscapeError::NonAsciiCharInByte => { let (c, span) = last_char(); @@ -213,23 +211,23 @@ pub(crate) fn emit_unescape_error( Applicability::MaybeIncorrect, ); } - err.emit(); + err.emit() } EscapeError::OutOfRangeHexEscape => { - dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)); + dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)) } EscapeError::LeadingUnderscoreUnicodeEscape => { let (c, span) = last_char(); dcx.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape { span, ch: escaped_char(c), - }); + }) } EscapeError::OverlongUnicodeEscape => { - dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)); + dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)) } EscapeError::UnclosedUnicodeEscape => { - dcx.emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())); + dcx.emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())) } EscapeError::NoBraceInUnicodeEscape => { let mut suggestion = "\\u{".to_owned(); @@ -248,23 +246,17 @@ pub(crate) fn emit_unescape_error( } else { (Some(err_span), NoBraceUnicodeSub::Help) }; - dcx.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }); + dcx.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }) } EscapeError::UnicodeEscapeInByte => { - dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)); + dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)) } EscapeError::EmptyUnicodeEscape => { - dcx.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)); - } - EscapeError::ZeroChars => { - dcx.emit_err(UnescapeError::ZeroChars(err_span)); - } - EscapeError::LoneSlash => { - dcx.emit_err(UnescapeError::LoneSlash(err_span)); - } - EscapeError::NulInCStr => { - dcx.emit_err(UnescapeError::NulInCStr { span: err_span }); + dcx.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)) } + EscapeError::ZeroChars => dcx.emit_err(UnescapeError::ZeroChars(err_span)), + EscapeError::LoneSlash => dcx.emit_err(UnescapeError::LoneSlash(err_span)), + EscapeError::NulInCStr => dcx.emit_err(UnescapeError::NulInCStr { span: err_span }), EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); dcx.emit_warn(UnescapeError::UnskippedWhitespace { @@ -272,11 +264,13 @@ pub(crate) fn emit_unescape_error( ch: escaped_char(c), char_span, }); + return None; } EscapeError::MultipleSkippedLinesWarning => { dcx.emit_warn(UnescapeError::MultipleSkippedLinesWarning(err_span)); + return None; } - } + }) } /// Pushes a character to a message string for error reporting diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1a57474bac2..2424b6c130d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2140,12 +2140,12 @@ impl<'a> Parser<'a> { Err(err) => { let span = token.uninterpolated_span(); self.bump(); - report_lit_error(self.sess, err, lit, span); + let guar = report_lit_error(self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err, symbol, lit.suffix); + let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix); Some( MetaItemLit::from_token_lit(lit, span) .unwrap_or_else(|_| unreachable!()), diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 623407eb380..dea2b9e6ca7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1459,7 +1459,7 @@ impl<'a> Parser<'a> { match self.parse_str_lit() { Ok(str_lit) => Some(str_lit), Err(Some(lit)) => match lit.kind { - ast::LitKind::Err => None, + ast::LitKind::Err(_) => None, _ => { self.dcx().emit_err(NonStringAbiLiteral { span: lit.span }); None diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 2fafbd6d97b..b0982029657 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -70,11 +70,11 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta } } Err(err) => { - report_lit_error(sess, err, token_lit, expr.span); + let guar = report_lit_error(sess, err, token_lit, expr.span); let lit = ast::MetaItemLit { symbol: token_lit.symbol, suffix: token_lit.suffix, - kind: ast::LitKind::Err, + kind: ast::LitKind::Err(guar), span: expr.span, }; MetaItemKind::NameValue(lit) diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c36cec6f353..82846e3b4e8 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,8 @@ use std::num::NonZeroU32; use rustc_ast::token; use rustc_ast::util::literal::LitError; use rustc_errors::{ - codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, + codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, + Level, MultiSpan, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -344,7 +345,12 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } -pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { +pub fn report_lit_error( + sess: &ParseSess, + err: LitError, + lit: token::Lit, + span: Span, +) -> ErrorGuaranteed { // 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()) @@ -372,47 +378,37 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..])) } - let token::Lit { kind, symbol, suffix, .. } = lit; let dcx = &sess.dcx; 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 { - dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }); - } + LitError::InvalidSuffix(suffix) => { + dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) } - LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix"); - let suf = suf.as_str(); + LitError::InvalidIntSuffix(suffix) => { + let suf = suffix.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); - } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) { - dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); + dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) + } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) { + dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { - dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); + dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } - LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix"); - let suf = suf.as_str(); + LitError::InvalidFloatSuffix(suffix) => { + let suf = suffix.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }); + dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) } else { - dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }); + dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) } } - LitError::NonDecimalFloat(base) => { - match base { - 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), - 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), - 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), - _ => unreachable!(), - }; - } + LitError::NonDecimalFloat(base) => match base { + 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), + 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), + _ => unreachable!(), + }, LitError::IntTooLarge(base) => { let max = u128::MAX; let limit = match base { @@ -421,7 +417,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: 16 => format!("{max:#x}"), _ => format!("{max}"), }; - dcx.emit_err(IntLiteralTooLarge { span, limit }); + dcx.emit_err(IntLiteralTooLarge { span, limit }) } } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 55e24b6491c..9b337f23867 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -337,7 +337,11 @@ pub enum LitKind { ByteStrRaw(u8), CStr, CStrRaw(u8), - Err, + // This should have an `ErrorGuaranteed`, except that type isn't available + // in this crate. (Imagine it is there.) Hence the `WithGuar` suffix. Must + // only be constructed in `LitKind::from_internal`, where an + // `ErrorGuaranteed` is available. + ErrWithGuar, } rpc_encode_decode!( @@ -352,7 +356,7 @@ rpc_encode_decode!( ByteStrRaw(n), CStr, CStrRaw(n), - Err, + ErrWithGuar, } ); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 90b76cbc26e..7c492941713 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1451,7 +1451,7 @@ impl Literal { f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix]) } - bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::Err => { + bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => { f(&[symbol, suffix]) } }) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 6595658b769..b8f7d966820 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -295,7 +295,8 @@ impl<'a> NormalizedPat<'a> { LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Int(val, _) => Self::LitInt(val.get()), LitKind::Bool(val) => Self::LitBool(val), - LitKind::Float(..) | LitKind::Err => Self::Wild, + LitKind::Float(..) => Self::Wild, + LitKind::Err(guar) => Self::Err(guar), }, _ => Self::Wild, }, diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index c8352c05265..079e6500e3c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -200,7 +200,7 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); } }, - LitKind::Err => (), + LitKind::Err(_) => (), LitKind::ByteStr(..) => { // We only lint if the type annotation is an array type (e.g. &[u8; 4]). // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 29c67341a46..a0a6382046d 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { match lit.value.node { LitKind::Bool(val) => kind!("Bool({val:?})"), LitKind::Char(c) => kind!("Char({c:?})"), - LitKind::Err => kind!("Err"), + LitKind::Err(_) => kind!("Err"), LitKind::Byte(b) => kind!("Byte({b})"), LitKind::Int(i, suffix) => { let int_ty = match suffix { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 61b38391d9e..79c691992a8 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -286,7 +286,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constan _ => bug!(), }, LitKind::Bool(b) => Constant::Bool(b), - LitKind::Err => Constant::Err, + LitKind::Err(_) => Constant::Err, } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs index c7c7bea9941..8a9d52a37a2 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs @@ -72,7 +72,7 @@ impl server::FreeFunctions for RaSpanServer { ) -> Result, ()> { // FIXME: keep track of LitKind and Suffix Ok(bridge::Literal { - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, s), suffix: None, span: self.call_site, @@ -202,7 +202,7 @@ impl server::TokenStream for RaSpanServer { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { // FIXME: handle literal kinds - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, &lit.text), // FIXME: handle suffixes suffix: None, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs index edbdc67b482..15a9e0deae4 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs @@ -64,7 +64,7 @@ impl server::FreeFunctions for TokenIdServer { ) -> Result, ()> { // FIXME: keep track of LitKind and Suffix Ok(bridge::Literal { - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, s), suffix: None, span: self.call_site, @@ -187,7 +187,7 @@ impl server::TokenStream for TokenIdServer { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { // FIXME: handle literal kinds - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, &lit.text), // FIXME: handle suffixes suffix: None,