Rollup merge of #121120 - nnethercote:LitKind-Err-guar, r=fmease

Add `ErrorGuaranteed` to `ast::LitKind::Err`, `token::LitKind::Err`.

Similar to recent work doing the same for `ExprKind::Err` (#120586) and `TyKind::Err` (#121109).

r? `@oli-obk`
This commit is contained in:
Guillaume Gomez 2024-02-15 14:33:03 +01:00 committed by GitHub
commit 06f53dd316
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 170 additions and 162 deletions

View File

@ -1846,7 +1846,7 @@ pub enum LitKind {
/// A boolean literal (`true`, `false`). /// A boolean literal (`true`, `false`).
Bool(bool), Bool(bool),
/// Placeholder for a literal that wasn't well-formed in some way. /// Placeholder for a literal that wasn't well-formed in some way.
Err, Err(ErrorGuaranteed),
} }
impl LitKind { impl LitKind {
@ -1893,7 +1893,7 @@ impl LitKind {
| LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Int(_, LitIntType::Unsuffixed)
| LitKind::Float(_, LitFloatType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)
| LitKind::Bool(..) | LitKind::Bool(..)
| LitKind::Err => false, | LitKind::Err(_) => false,
} }
} }
} }

View File

@ -13,7 +13,7 @@ use rustc_macros::HashStable_Generic;
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{kw, sym};
#[allow(hidden_glob_reexports)] #[allow(hidden_glob_reexports)]
use rustc_span::symbol::{Ident, Symbol}; 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::borrow::Cow;
use std::fmt; use std::fmt;
@ -75,7 +75,7 @@ pub enum LitKind {
ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols
CStr, CStr,
CStrRaw(u8), CStrRaw(u8),
Err, Err(ErrorGuaranteed),
} }
/// A literal token. /// A literal token.
@ -144,7 +144,7 @@ impl fmt::Display for Lit {
CStrRaw(n) => { CStrRaw(n) => {
write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))? 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 { if let Some(suffix) = suffix {
@ -159,7 +159,7 @@ impl LitKind {
/// An English article for the literal token kind. /// An English article for the literal token kind.
pub fn article(self) -> &'static str { pub fn article(self) -> &'static str {
match self { match self {
Integer | Err => "an", Integer | Err(_) => "an",
_ => "a", _ => "a",
} }
} }
@ -174,12 +174,12 @@ impl LitKind {
Str | StrRaw(..) => "string", Str | StrRaw(..) => "string",
ByteStr | ByteStrRaw(..) => "byte string", ByteStr | ByteStrRaw(..) => "byte string",
CStr | CStrRaw(..) => "C string", CStr | CStrRaw(..) => "C string",
Err => "error", Err(_) => "error",
} }
} }
pub(crate) fn may_have_suffix(self) -> bool { pub(crate) fn may_have_suffix(self) -> bool {
matches!(self, Integer | Float | Err) matches!(self, Integer | Float | Err(_))
} }
} }

View File

@ -31,20 +31,21 @@ pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol {
#[derive(Debug)] #[derive(Debug)]
pub enum LitError { pub enum LitError {
LexerError, InvalidSuffix(Symbol),
InvalidSuffix, InvalidIntSuffix(Symbol),
InvalidIntSuffix, InvalidFloatSuffix(Symbol),
InvalidFloatSuffix, NonDecimalFloat(u32), // u32 is the base
NonDecimalFloat(u32), IntTooLarge(u32), // u32 is the base
IntTooLarge(u32),
} }
impl LitKind { impl LitKind {
/// Converts literal token into a semantic literal. /// Converts literal token into a semantic literal.
pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> { pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
let token::Lit { kind, symbol, suffix } = lit; let token::Lit { kind, symbol, suffix } = lit;
if suffix.is_some() && !kind.may_have_suffix() { if let Some(suffix) = suffix
return Err(LitError::InvalidSuffix); && !kind.may_have_suffix()
{
return Err(LitError::InvalidSuffix(suffix));
} }
// For byte/char/string literals, chars and escapes have already been // For byte/char/string literals, chars and escapes have already been
@ -145,7 +146,7 @@ impl LitKind {
buf.push(0); buf.push(0);
LitKind::CStr(buf.into(), StrStyle::Raw(n)) 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::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 // This only shows up in places like `-Zunpretty=hir` output, so we
// don't bother to produce something useful. // don't bother to produce something useful.
write!(f, "<bad-literal>")?; write!(f, "<bad-literal>")?;
@ -238,7 +239,7 @@ impl MetaItemLit {
LitKind::Char(_) => token::Char, LitKind::Char(_) => token::Char,
LitKind::Int(..) => token::Integer, LitKind::Int(..) => token::Integer,
LitKind::Float(..) => token::Float, LitKind::Float(..) => token::Float,
LitKind::Err => token::Err, LitKind::Err(guar) => token::Err(guar),
}; };
token::Lit::new(kind, self.symbol, self.suffix) token::Lit::new(kind, self.symbol, self.suffix)
@ -272,12 +273,12 @@ fn filtered_float_lit(
return Err(LitError::NonDecimalFloat(base)); return Err(LitError::NonDecimalFloat(base));
} }
Ok(match suffix { Ok(match suffix {
Some(suf) => LitKind::Float( Some(suffix) => LitKind::Float(
symbol, symbol,
ast::LitFloatType::Suffixed(match suf { ast::LitFloatType::Suffixed(match suffix {
sym::f32 => ast::FloatTy::F32, sym::f32 => ast::FloatTy::F32,
sym::f64 => ast::FloatTy::F64, sym::f64 => ast::FloatTy::F64,
_ => return Err(LitError::InvalidFloatSuffix), _ => return Err(LitError::InvalidFloatSuffix(suffix)),
}), }),
), ),
None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed), None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed),
@ -318,17 +319,13 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
// `1f64` and `2f32` etc. are valid float literals, and // `1f64` and `2f32` etc. are valid float literals, and
// `fxxx` looks more like an invalid float literal than invalid integer literal. // `fxxx` looks more like an invalid float literal than invalid integer literal.
_ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base), _ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base),
_ => return Err(LitError::InvalidIntSuffix), _ => return Err(LitError::InvalidIntSuffix(suf)),
}, },
_ => ast::LitIntType::Unsuffixed, _ => ast::LitIntType::Unsuffixed,
}; };
let s = &s[if base != 10 { 2 } else { 0 }..]; let s = &s[if base != 10 { 2 } else { 0 }..];
u128::from_str_radix(s, base).map(|i| LitKind::Int(i.into(), ty)).map_err(|_| { u128::from_str_radix(s, base)
// Small bases are lexed as if they were base 10, e.g, the string .map(|i| LitKind::Int(i.into(), ty))
// might be `0b10201`. This will cause the conversion above to fail, .map_err(|_| LitError::IntTooLarge(base))
// 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) }
})
} }

View File

@ -124,8 +124,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let lit_kind = match LitKind::from_token_lit(*token_lit) { let lit_kind = match LitKind::from_token_lit(*token_lit) {
Ok(lit_kind) => lit_kind, Ok(lit_kind) => lit_kind,
Err(err) => { Err(err) => {
report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span); let guar = report_lit_error(
LitKind::Err &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)); let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));

View File

@ -966,10 +966,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
{ {
lit lit
} else { } else {
let guar = self.dcx().has_errors().unwrap();
MetaItemLit { MetaItemLit {
symbol: kw::Empty, symbol: kw::Empty,
suffix: None, suffix: None,
kind: LitKind::Err, kind: LitKind::Err(guar),
span: DUMMY_SP, span: DUMMY_SP,
} }
}; };

View File

@ -254,7 +254,7 @@ fn literal_to_string(lit: token::Lit) -> String {
token::CStrRaw(n) => { token::CStrRaw(n) => {
format!("cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize)) 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 { if let Some(suffix) = suffix {

View File

@ -40,7 +40,7 @@ pub fn expand_concat(
cx.dcx().emit_err(errors::ConcatBytestr { span: e.span }); cx.dcx().emit_err(errors::ConcatBytestr { span: e.span });
has_errors = true; has_errors = true;
} }
Ok(ast::LitKind::Err) => { Ok(ast::LitKind::Err(_)) => {
has_errors = true; has_errors = true;
} }
Err(err) => { Err(err) => {

View File

@ -44,7 +44,7 @@ fn invalid_type_err(
Ok(ast::LitKind::Bool(_)) => { Ok(ast::LitKind::Bool(_)) => {
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None }); 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 => { Ok(ast::LitKind::Int(_, _)) if !is_nested => {
let sugg = let sugg =
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet }); snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet });

View File

@ -1266,7 +1266,7 @@ pub fn expr_to_spanned_string<'a>(
); );
Some((err, true)) Some((err, true))
} }
Ok(ast::LitKind::Err) => None, Ok(ast::LitKind::Err(_)) => None,
Err(err) => { Err(err) => {
report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span); report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span);
None None

View File

@ -10,7 +10,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc; 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::lexer::nfc_normalize;
use rustc_parse::parse_stream_from_source_str; use rustc_parse::parse_stream_from_source_str;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -63,7 +63,12 @@ impl FromInternal<token::LitKind> for LitKind {
token::ByteStrRaw(n) => LitKind::ByteStrRaw(n), token::ByteStrRaw(n) => LitKind::ByteStrRaw(n),
token::CStr => LitKind::CStr, token::CStr => LitKind::CStr,
token::CStrRaw(n) => LitKind::CStrRaw(n), 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!(), token::Bool => unreachable!(),
} }
} }
@ -82,7 +87,16 @@ impl ToInternal<token::LitKind> for LitKind {
LitKind::ByteStrRaw(n) => token::ByteStrRaw(n), LitKind::ByteStrRaw(n) => token::ByteStrRaw(n),
LitKind::CStr => token::CStr, LitKind::CStr => token::CStr,
LitKind::CStrRaw(n) => token::CStrRaw(n), 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::ByteStrRaw(_)
| token::LitKind::CStr | token::LitKind::CStr
| token::LitKind::CStrRaw(_) | token::LitKind::CStrRaw(_)
| token::LitKind::Err => return Err(()), | token::LitKind::Err(_) => return Err(()),
token::LitKind::Integer | token::LitKind::Float => {} token::LitKind::Integer | token::LitKind::Float => {}
} }

View File

@ -1319,7 +1319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span))) tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span)))
.skip_binder(), .skip_binder(),
), ),
ast::LitKind::Err => Ty::new_misc_error(tcx), ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
} }
} }

View File

@ -164,11 +164,7 @@ fn lit_to_mir_constant<'tcx>(
})?, })?,
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (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::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
(ast::LitKind::Err, _) => { (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)),
return Err(LitToConstError::Reported(
tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"),
));
}
_ => return Err(LitToConstError::TypeError), _ => return Err(LitToConstError::TypeError),
}; };

View File

@ -71,11 +71,7 @@ pub(crate) fn lit_to_const<'tcx>(
ty::ValTree::from_scalar_int(bits) ty::ValTree::from_scalar_int(bits)
} }
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
(ast::LitKind::Err, _) => { (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)),
return Err(LitToConstError::Reported(
tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"),
));
}
_ => return Err(LitToConstError::TypeError), _ => return Err(LitToConstError::TypeError),
}; };

View File

@ -897,12 +897,14 @@ impl<'tcx> Cx<'tcx> {
let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local()); 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 generics = self.tcx.generics_of(hir_id.owner);
let Some(&index) = generics.param_def_id_to_index.get(&def_id) else { 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 // We already errored about a late bound const
return ExprKind::Literal {
lit: &Spanned { span: DUMMY_SP, node: LitKind::Err }, let lit = self
neg: false, .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 name = self.tcx.hir().name(hir_id);
let param = ty::ParamConst::new(index, name); let param = ty::ParamConst::new(index, name);

View File

@ -16,7 +16,7 @@ use rustc_session::lint::builtin::{
}; };
use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::Symbol;
use rustc_span::{edition::Edition, BytePos, Pos, Span}; use rustc_span::{edition::Edition, BytePos, Pos, Span};
mod diagnostics; mod diagnostics;
@ -478,12 +478,12 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
} }
} }
rustc_lexer::LiteralKind::Int { base, empty_int } => { rustc_lexer::LiteralKind::Int { base, empty_int } => {
let mut kind = token::Integer;
if empty_int { if empty_int {
let span = self.mk_sp(start, end); let span = self.mk_sp(start, end);
self.dcx().emit_err(errors::NoDigitsLiteral { span }); let guar = self.dcx().emit_err(errors::NoDigitsLiteral { span });
(token::Integer, sym::integer(0)) kind = token::Err(guar);
} else { } else if matches!(base, Base::Binary | Base::Octal) {
if matches!(base, Base::Binary | Base::Octal) {
let base = base as u32; let base = base as u32;
let s = self.str_from_to(start + BytePos(2), end); let s = self.str_from_to(start + BytePos(2), end);
for (idx, c) in s.char_indices() { for (idx, c) in s.char_indices() {
@ -492,12 +492,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
start + BytePos::from_usize(2 + idx + c.len_utf8()), start + BytePos::from_usize(2 + idx + c.len_utf8()),
); );
if c != '_' && c.to_digit(base).is_none() { if c != '_' && c.to_digit(base).is_none() {
let guar =
self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); 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 } => { rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
if empty_exponent { if empty_exponent {
@ -691,7 +692,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
fn cook_common( fn cook_common(
&self, &self,
kind: token::LitKind, mut kind: token::LitKind,
mode: Mode, mode: Mode,
start: BytePos, start: BytePos,
end: BytePos, end: BytePos,
@ -699,7 +700,6 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
postfix_len: u32, postfix_len: u32,
unescape: fn(&str, Mode, &mut dyn FnMut(Range<usize>, Result<(), EscapeError>)), unescape: fn(&str, Mode, &mut dyn FnMut(Range<usize>, Result<(), EscapeError>)),
) -> (token::LitKind, Symbol) { ) -> (token::LitKind, Symbol) {
let mut has_fatal_err = false;
let content_start = start + BytePos(prefix_len); let content_start = start + BytePos(prefix_len);
let content_end = end - BytePos(postfix_len); let content_end = end - BytePos(postfix_len);
let lit_content = self.str_from_to(content_start, content_end); 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 lo = content_start + BytePos(start);
let hi = lo + BytePos(end - start); let hi = lo + BytePos(end - start);
let span = self.mk_sp(lo, hi); let span = self.mk_sp(lo, hi);
if err.is_fatal() { let is_fatal = err.is_fatal();
has_fatal_err = true; if let Some(guar) = emit_unescape_error(
}
emit_unescape_error(
self.dcx(), self.dcx(),
lit_content, lit_content,
span_with_quotes, span_with_quotes,
@ -722,17 +720,21 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
mode, mode,
range, range,
err, err,
); ) {
assert!(is_fatal);
kind = token::Err(guar);
}
} }
}); });
// We normally exclude the quotes for the symbol, but for errors we // We normally exclude the quotes for the symbol, but for errors we
// include it because it results in clearer error messages. // include it because it results in clearer error messages.
if !has_fatal_err { let sym = if !matches!(kind, token::Err(_)) {
(kind, Symbol::intern(lit_content)) Symbol::intern(lit_content)
} else { } else {
(token::Err, self.symbol_from_to(start, end)) self.symbol_from_to(start, end)
} };
(kind, sym)
} }
fn cook_unicode( fn cook_unicode(

View File

@ -3,7 +3,7 @@
use std::iter::once; use std::iter::once;
use std::ops::Range; use std::ops::Range;
use rustc_errors::{Applicability, DiagCtxt}; use rustc_errors::{Applicability, DiagCtxt, ErrorGuaranteed};
use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_lexer::unescape::{EscapeError, Mode};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -21,7 +21,7 @@ pub(crate) fn emit_unescape_error(
// range of the error inside `lit` // range of the error inside `lit`
range: Range<usize>, range: Range<usize>,
error: EscapeError, error: EscapeError,
) { ) -> Option<ErrorGuaranteed> {
debug!( debug!(
"emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}", "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}",
lit, full_lit_span, mode, range, 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)); let span = err_span.with_lo(err_span.hi() - BytePos(c.len_utf8() as u32));
(c, span) (c, span)
}; };
match error { Some(match error {
EscapeError::LoneSurrogateUnicodeEscape => { EscapeError::LoneSurrogateUnicodeEscape => {
dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }); dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true })
} }
EscapeError::OutOfRangeUnicodeEscape => { EscapeError::OutOfRangeUnicodeEscape => {
dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }); dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false })
} }
EscapeError::MoreThanOneChar => { EscapeError::MoreThanOneChar => {
use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
@ -106,7 +106,7 @@ pub(crate) fn emit_unescape_error(
span: full_lit_span, span: full_lit_span,
note, note,
suggestion: sugg, suggestion: sugg,
}); })
} }
EscapeError::EscapeOnlyChar => { EscapeError::EscapeOnlyChar => {
let (c, char_span) = last_char(); let (c, char_span) = last_char();
@ -116,15 +116,15 @@ pub(crate) fn emit_unescape_error(
escaped_sugg: c.escape_default().to_string(), escaped_sugg: c.escape_default().to_string(),
escaped_msg: escaped_char(c), escaped_msg: escaped_char(c),
byte: mode == Mode::Byte, byte: mode == Mode::Byte,
}); })
} }
EscapeError::BareCarriageReturn => { EscapeError::BareCarriageReturn => {
let double_quotes = mode.in_double_quotes(); 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 => { EscapeError::BareCarriageReturnInRawString => {
assert!(mode.in_double_quotes()); assert!(mode.in_double_quotes());
dcx.emit_err(UnescapeError::BareCrRawString(err_span)); dcx.emit_err(UnescapeError::BareCrRawString(err_span))
} }
EscapeError::InvalidEscape => { EscapeError::InvalidEscape => {
let (c, span) = last_char(); let (c, span) = last_char();
@ -161,16 +161,14 @@ pub(crate) fn emit_unescape_error(
<https://doc.rust-lang.org/reference/tokens.html#literals>", <https://doc.rust-lang.org/reference/tokens.html#literals>",
); );
} }
diag.emit(); diag.emit()
}
EscapeError::TooShortHexEscape => {
dcx.emit_err(UnescapeError::TooShortHexEscape(err_span));
} }
EscapeError::TooShortHexEscape => dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)),
EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
let (c, span) = last_char(); let (c, span) = last_char();
let is_hex = error == EscapeError::InvalidCharInHexEscape; let is_hex = error == EscapeError::InvalidCharInHexEscape;
let ch = escaped_char(c); 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 => { EscapeError::NonAsciiCharInByte => {
let (c, span) = last_char(); let (c, span) = last_char();
@ -213,23 +211,23 @@ pub(crate) fn emit_unescape_error(
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
err.emit(); err.emit()
} }
EscapeError::OutOfRangeHexEscape => { EscapeError::OutOfRangeHexEscape => {
dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)); dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span))
} }
EscapeError::LeadingUnderscoreUnicodeEscape => { EscapeError::LeadingUnderscoreUnicodeEscape => {
let (c, span) = last_char(); let (c, span) = last_char();
dcx.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape { dcx.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape {
span, span,
ch: escaped_char(c), ch: escaped_char(c),
}); })
} }
EscapeError::OverlongUnicodeEscape => { EscapeError::OverlongUnicodeEscape => {
dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)); dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span))
} }
EscapeError::UnclosedUnicodeEscape => { 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 => { EscapeError::NoBraceInUnicodeEscape => {
let mut suggestion = "\\u{".to_owned(); let mut suggestion = "\\u{".to_owned();
@ -248,23 +246,17 @@ pub(crate) fn emit_unescape_error(
} else { } else {
(Some(err_span), NoBraceUnicodeSub::Help) (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 => { EscapeError::UnicodeEscapeInByte => {
dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)); dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span))
} }
EscapeError::EmptyUnicodeEscape => { EscapeError::EmptyUnicodeEscape => {
dcx.emit_err(UnescapeError::EmptyUnicodeEscape(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::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 => { EscapeError::UnskippedWhitespaceWarning => {
let (c, char_span) = last_char(); let (c, char_span) = last_char();
dcx.emit_warn(UnescapeError::UnskippedWhitespace { dcx.emit_warn(UnescapeError::UnskippedWhitespace {
@ -272,11 +264,13 @@ pub(crate) fn emit_unescape_error(
ch: escaped_char(c), ch: escaped_char(c),
char_span, char_span,
}); });
return None;
} }
EscapeError::MultipleSkippedLinesWarning => { EscapeError::MultipleSkippedLinesWarning => {
dcx.emit_warn(UnescapeError::MultipleSkippedLinesWarning(err_span)); dcx.emit_warn(UnescapeError::MultipleSkippedLinesWarning(err_span));
return None;
} }
} })
} }
/// Pushes a character to a message string for error reporting /// Pushes a character to a message string for error reporting

View File

@ -2140,12 +2140,12 @@ impl<'a> Parser<'a> {
Err(err) => { Err(err) => {
let span = token.uninterpolated_span(); let span = token.uninterpolated_span();
self.bump(); 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 // Pack possible quotes and prefixes from the original literal into
// the error literal's symbol so they can be pretty-printed faithfully. // the error literal's symbol so they can be pretty-printed faithfully.
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
let symbol = Symbol::intern(&suffixless_lit.to_string()); 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( Some(
MetaItemLit::from_token_lit(lit, span) MetaItemLit::from_token_lit(lit, span)
.unwrap_or_else(|_| unreachable!()), .unwrap_or_else(|_| unreachable!()),

View File

@ -1459,7 +1459,7 @@ impl<'a> Parser<'a> {
match self.parse_str_lit() { match self.parse_str_lit() {
Ok(str_lit) => Some(str_lit), Ok(str_lit) => Some(str_lit),
Err(Some(lit)) => match lit.kind { Err(Some(lit)) => match lit.kind {
ast::LitKind::Err => None, ast::LitKind::Err(_) => None,
_ => { _ => {
self.dcx().emit_err(NonStringAbiLiteral { span: lit.span }); self.dcx().emit_err(NonStringAbiLiteral { span: lit.span });
None None

View File

@ -70,11 +70,11 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
} }
} }
Err(err) => { 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 { let lit = ast::MetaItemLit {
symbol: token_lit.symbol, symbol: token_lit.symbol,
suffix: token_lit.suffix, suffix: token_lit.suffix,
kind: ast::LitKind::Err, kind: ast::LitKind::Err(guar),
span: expr.span, span: expr.span,
}; };
MetaItemKind::NameValue(lit) MetaItemKind::NameValue(lit)

View File

@ -3,7 +3,8 @@ use std::num::NonZeroU32;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::util::literal::LitError; use rustc_ast::util::literal::LitError;
use rustc_errors::{ use rustc_errors::{
codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
Level, MultiSpan,
}; };
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
@ -344,7 +345,12 @@ pub(crate) struct BinaryFloatLiteralNotSupported {
pub span: Span, 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. // Checks if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { 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()) 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..])) valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
} }
let token::Lit { kind, symbol, suffix, .. } = lit;
let dcx = &sess.dcx; let dcx = &sess.dcx;
match err { match err {
// `LexerError` is an error, but it was already reported LitError::InvalidSuffix(suffix) => {
// by lexer, so here we don't report it the second time. dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
LitError::LexerError => {}
LitError::InvalidSuffix => {
if let Some(suffix) = suffix {
dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix });
} }
} LitError::InvalidIntSuffix(suffix) => {
LitError::InvalidIntSuffix => { let suf = suffix.as_str();
let suf = suffix.expect("suffix error with no suffix");
let suf = suf.as_str();
if looks_like_width_suffix(&['i', 'u'], suf) { if looks_like_width_suffix(&['i', 'u'], suf) {
// If it looks like a width, try to be helpful. // If it looks like a width, try to be helpful.
dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
} else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) { } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
} else { } else {
dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
} }
} }
LitError::InvalidFloatSuffix => { LitError::InvalidFloatSuffix(suffix) => {
let suf = suffix.expect("suffix error with no suffix"); let suf = suffix.as_str();
let suf = suf.as_str();
if looks_like_width_suffix(&['f'], suf) { if looks_like_width_suffix(&['f'], suf) {
// If it looks like a width, try to be helpful. // 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 { } else {
dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }); dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
} }
} }
LitError::NonDecimalFloat(base) => { LitError::NonDecimalFloat(base) => match base {
match base {
16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }),
8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }),
2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }),
_ => unreachable!(), _ => unreachable!(),
}; },
}
LitError::IntTooLarge(base) => { LitError::IntTooLarge(base) => {
let max = u128::MAX; let max = u128::MAX;
let limit = match base { 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}"), 16 => format!("{max:#x}"),
_ => format!("{max}"), _ => format!("{max}"),
}; };
dcx.emit_err(IntLiteralTooLarge { span, limit }); dcx.emit_err(IntLiteralTooLarge { span, limit })
} }
} }
} }

View File

@ -337,7 +337,11 @@ pub enum LitKind {
ByteStrRaw(u8), ByteStrRaw(u8),
CStr, CStr,
CStrRaw(u8), 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!( rpc_encode_decode!(
@ -352,7 +356,7 @@ rpc_encode_decode!(
ByteStrRaw(n), ByteStrRaw(n),
CStr, CStr,
CStrRaw(n), CStrRaw(n),
Err, ErrWithGuar,
} }
); );

View File

@ -1451,7 +1451,7 @@ impl Literal {
f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix]) 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]) f(&[symbol, suffix])
} }
}) })

View File

@ -295,7 +295,8 @@ impl<'a> NormalizedPat<'a> {
LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()),
LitKind::Int(val, _) => Self::LitInt(val.get()), LitKind::Int(val, _) => Self::LitInt(val.get()),
LitKind::Bool(val) => Self::LitBool(val), LitKind::Bool(val) => Self::LitBool(val),
LitKind::Float(..) | LitKind::Err => Self::Wild, LitKind::Float(..) => Self::Wild,
LitKind::Err(guar) => Self::Err(guar),
}, },
_ => Self::Wild, _ => Self::Wild,
}, },

View File

@ -200,7 +200,7 @@ impl LateLintPass<'_> for RedundantTypeAnnotations {
span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
} }
}, },
LitKind::Err => (), LitKind::Err(_) => (),
LitKind::ByteStr(..) => { LitKind::ByteStr(..) => {
// We only lint if the type annotation is an array type (e.g. &[u8; 4]). // 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 // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we

View File

@ -279,7 +279,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
match lit.value.node { match lit.value.node {
LitKind::Bool(val) => kind!("Bool({val:?})"), LitKind::Bool(val) => kind!("Bool({val:?})"),
LitKind::Char(c) => kind!("Char({c:?})"), LitKind::Char(c) => kind!("Char({c:?})"),
LitKind::Err => kind!("Err"), LitKind::Err(_) => kind!("Err"),
LitKind::Byte(b) => kind!("Byte({b})"), LitKind::Byte(b) => kind!("Byte({b})"),
LitKind::Int(i, suffix) => { LitKind::Int(i, suffix) => {
let int_ty = match suffix { let int_ty = match suffix {

View File

@ -286,7 +286,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
_ => bug!(), _ => bug!(),
}, },
LitKind::Bool(b) => Constant::Bool(b), LitKind::Bool(b) => Constant::Bool(b),
LitKind::Err => Constant::Err, LitKind::Err(_) => Constant::Err,
} }
} }

View File

@ -72,7 +72,7 @@ impl server::FreeFunctions for RaSpanServer {
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> { ) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
// FIXME: keep track of LitKind and Suffix // FIXME: keep track of LitKind and Suffix
Ok(bridge::Literal { Ok(bridge::Literal {
kind: bridge::LitKind::Err, kind: bridge::LitKind::Integer, // dummy
symbol: Symbol::intern(self.interner, s), symbol: Symbol::intern(self.interner, s),
suffix: None, suffix: None,
span: self.call_site, span: self.call_site,
@ -202,7 +202,7 @@ impl server::TokenStream for RaSpanServer {
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
bridge::TokenTree::Literal(bridge::Literal { bridge::TokenTree::Literal(bridge::Literal {
// FIXME: handle literal kinds // FIXME: handle literal kinds
kind: bridge::LitKind::Err, kind: bridge::LitKind::Integer, // dummy
symbol: Symbol::intern(self.interner, &lit.text), symbol: Symbol::intern(self.interner, &lit.text),
// FIXME: handle suffixes // FIXME: handle suffixes
suffix: None, suffix: None,

View File

@ -64,7 +64,7 @@ impl server::FreeFunctions for TokenIdServer {
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> { ) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
// FIXME: keep track of LitKind and Suffix // FIXME: keep track of LitKind and Suffix
Ok(bridge::Literal { Ok(bridge::Literal {
kind: bridge::LitKind::Err, kind: bridge::LitKind::Integer, // dummy
symbol: Symbol::intern(self.interner, s), symbol: Symbol::intern(self.interner, s),
suffix: None, suffix: None,
span: self.call_site, span: self.call_site,
@ -187,7 +187,7 @@ impl server::TokenStream for TokenIdServer {
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
bridge::TokenTree::Literal(bridge::Literal { bridge::TokenTree::Literal(bridge::Literal {
// FIXME: handle literal kinds // FIXME: handle literal kinds
kind: bridge::LitKind::Err, kind: bridge::LitKind::Integer, // dummy
symbol: Symbol::intern(self.interner, &lit.text), symbol: Symbol::intern(self.interner, &lit.text),
// FIXME: handle suffixes // FIXME: handle suffixes
suffix: None, suffix: None,