Add ErrorGuaranteed to ast::ExprKind::Err
This commit is contained in:
@@ -2,7 +2,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_span::Span;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
@@ -12,7 +12,7 @@ fn invalid_type_err(
|
||||
token_lit: ast::token::Lit,
|
||||
span: Span,
|
||||
is_nested: bool,
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
use errors::{
|
||||
ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
|
||||
};
|
||||
@@ -22,12 +22,12 @@ fn invalid_type_err(
|
||||
Ok(ast::LitKind::CStr(_, _)) => {
|
||||
// Avoid ambiguity in handling of terminal `NUL` by refusing to
|
||||
// concatenate C string literals as bytes.
|
||||
dcx.emit_err(errors::ConcatCStrLit { span: span });
|
||||
dcx.emit_err(errors::ConcatCStrLit { span })
|
||||
}
|
||||
Ok(ast::LitKind::Char(_)) => {
|
||||
let sugg =
|
||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg })
|
||||
}
|
||||
Ok(ast::LitKind::Str(_, _)) => {
|
||||
// suggestion would be invalid if we are nested
|
||||
@@ -36,86 +36,79 @@ fn invalid_type_err(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg })
|
||||
}
|
||||
Ok(ast::LitKind::Float(_, _)) => {
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None })
|
||||
}
|
||||
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::Int(_, _)) if !is_nested => {
|
||||
let sugg =
|
||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg })
|
||||
}
|
||||
Ok(ast::LitKind::Int(
|
||||
val,
|
||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||
)) => {
|
||||
assert!(val.get() > u8::MAX.into()); // must be an error
|
||||
dcx.emit_err(ConcatBytesOob { span });
|
||||
}
|
||||
Ok(ast::LitKind::Int(_, _)) => {
|
||||
dcx.emit_err(ConcatBytesNonU8 { span });
|
||||
dcx.emit_err(ConcatBytesOob { span })
|
||||
}
|
||||
Ok(ast::LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }),
|
||||
Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
|
||||
Err(err) => {
|
||||
report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
|
||||
}
|
||||
Ok(ast::LitKind::Err(guar)) => guar,
|
||||
Err(err) => report_lit_error(&cx.sess.parse_sess, err, token_lit, span),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `expr` as a *single* byte literal if applicable.
|
||||
///
|
||||
/// Otherwise, returns `None`, and either pushes the `expr`'s span to `missing_literals` or
|
||||
/// updates `guar` accordingly.
|
||||
fn handle_array_element(
|
||||
cx: &mut base::ExtCtxt<'_>,
|
||||
has_errors: &mut bool,
|
||||
guar: &mut Option<ErrorGuaranteed>,
|
||||
missing_literals: &mut Vec<rustc_span::Span>,
|
||||
expr: &P<rustc_ast::Expr>,
|
||||
) -> Option<u8> {
|
||||
let dcx = cx.dcx();
|
||||
match expr.kind {
|
||||
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
|
||||
if !*has_errors {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
||||
}
|
||||
*has_errors = true;
|
||||
None
|
||||
}
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Int(
|
||||
val,
|
||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||
)) if val.get() <= u8::MAX.into() => Some(val.get() as u8),
|
||||
|
||||
Ok(ast::LitKind::Byte(val)) => Some(val),
|
||||
Ok(ast::LitKind::ByteStr(..)) => {
|
||||
if !*has_errors {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true });
|
||||
match expr.kind {
|
||||
ast::ExprKind::Lit(token_lit) => {
|
||||
match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Int(
|
||||
val,
|
||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||
)) if let Ok(val) = u8::try_from(val.get()) => {
|
||||
return Some(val);
|
||||
}
|
||||
*has_errors = true;
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
if !*has_errors {
|
||||
invalid_type_err(cx, token_lit, expr.span, true);
|
||||
Ok(ast::LitKind::Byte(val)) => return Some(val),
|
||||
Ok(ast::LitKind::ByteStr(..)) => {
|
||||
guar.get_or_insert_with(|| {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true })
|
||||
});
|
||||
}
|
||||
*has_errors = true;
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, expr.span, true));
|
||||
}
|
||||
};
|
||||
}
|
||||
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
|
||||
guar.get_or_insert_with(|| {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
|
||||
});
|
||||
}
|
||||
ast::ExprKind::IncludedBytes(..) => {
|
||||
if !*has_errors {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
||||
}
|
||||
*has_errors = true;
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
missing_literals.push(expr.span);
|
||||
None
|
||||
guar.get_or_insert_with(|| {
|
||||
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
|
||||
});
|
||||
}
|
||||
_ => missing_literals.push(expr.span),
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn expand_concat_bytes(
|
||||
@@ -123,18 +116,19 @@ pub fn expand_concat_bytes(
|
||||
sp: rustc_span::Span,
|
||||
tts: TokenStream,
|
||||
) -> Box<dyn base::MacResult + 'static> {
|
||||
let Some(es) = base::get_exprs_from_tts(cx, tts) else {
|
||||
return DummyResult::any(sp);
|
||||
let es = match base::get_exprs_from_tts(cx, tts) {
|
||||
Ok(es) => es,
|
||||
Err(guar) => return DummyResult::any(sp, guar),
|
||||
};
|
||||
let mut accumulator = Vec::new();
|
||||
let mut missing_literals = vec![];
|
||||
let mut has_errors = false;
|
||||
let mut guar = None;
|
||||
for e in es {
|
||||
match &e.kind {
|
||||
ast::ExprKind::Array(exprs) => {
|
||||
for expr in exprs {
|
||||
if let Some(elem) =
|
||||
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
||||
handle_array_element(cx, &mut guar, &mut missing_literals, expr)
|
||||
{
|
||||
accumulator.push(elem);
|
||||
}
|
||||
@@ -146,14 +140,16 @@ pub fn expand_concat_bytes(
|
||||
ast::LitKind::from_token_lit(token_lit)
|
||||
{
|
||||
if let Some(elem) =
|
||||
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
||||
handle_array_element(cx, &mut guar, &mut missing_literals, expr)
|
||||
{
|
||||
for _ in 0..count_val.get() {
|
||||
accumulator.push(elem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cx.dcx().emit_err(errors::ConcatBytesBadRepeat { span: count.value.span });
|
||||
guar = Some(
|
||||
cx.dcx().emit_err(errors::ConcatBytesBadRepeat { span: count.value.span }),
|
||||
);
|
||||
}
|
||||
}
|
||||
&ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
@@ -164,17 +160,14 @@ pub fn expand_concat_bytes(
|
||||
accumulator.extend_from_slice(bytes);
|
||||
}
|
||||
_ => {
|
||||
if !has_errors {
|
||||
invalid_type_err(cx, token_lit, e.span, false);
|
||||
}
|
||||
has_errors = true;
|
||||
guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, e.span, false));
|
||||
}
|
||||
},
|
||||
ast::ExprKind::IncludedBytes(bytes) => {
|
||||
accumulator.extend_from_slice(bytes);
|
||||
}
|
||||
ast::ExprKind::Err => {
|
||||
has_errors = true;
|
||||
ast::ExprKind::Err(guarantee) => {
|
||||
guar = Some(*guarantee);
|
||||
}
|
||||
ast::ExprKind::Dummy => cx.dcx().span_bug(e.span, "concatenating `ExprKind::Dummy`"),
|
||||
_ => {
|
||||
@@ -183,10 +176,10 @@ pub fn expand_concat_bytes(
|
||||
}
|
||||
}
|
||||
if !missing_literals.is_empty() {
|
||||
cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
|
||||
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
||||
} else if has_errors {
|
||||
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
||||
let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
|
||||
return base::MacEager::expr(DummyResult::raw_expr(sp, Some(guar)));
|
||||
} else if let Some(guar) = guar {
|
||||
return base::MacEager::expr(DummyResult::raw_expr(sp, Some(guar)));
|
||||
}
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
base::MacEager::expr(cx.expr_byte_str(sp, accumulator))
|
||||
|
||||
Reference in New Issue
Block a user