summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_builtin_macros/src/concat_bytes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src/concat_bytes.rs')
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs108
1 files changed, 64 insertions, 44 deletions
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 66e86bf21..d1124145d 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -2,18 +2,22 @@ use rustc_ast as ast;
use rustc_ast::{ptr::P, tokenstream::TokenStream};
use rustc_errors::Applicability;
use rustc_expand::base::{self, DummyResult};
+use rustc_session::errors::report_lit_error;
+use rustc_span::Span;
/// Emits errors for literal expressions that are invalid inside and outside of an array.
-fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_nested: bool) {
- let ast::ExprKind::Lit(lit) = &expr.kind else {
- unreachable!();
- };
- match lit.kind {
- ast::LitKind::Char(_) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+fn invalid_type_err(
+ cx: &mut base::ExtCtxt<'_>,
+ token_lit: ast::token::Lit,
+ span: Span,
+ is_nested: bool,
+) {
+ match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Char(_)) => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate character literals");
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try using a byte character",
format!("b{}", snippet),
Applicability::MachineApplicable,
@@ -21,13 +25,13 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
.emit();
}
}
- ast::LitKind::Str(_, _) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals");
+ Ok(ast::LitKind::Str(_, _)) => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate string literals");
// suggestion would be invalid if we are nested
if !is_nested {
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try using a byte string",
format!("b{}", snippet),
Applicability::MachineApplicable,
@@ -36,18 +40,18 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
}
err.emit();
}
- ast::LitKind::Float(_, _) => {
- cx.span_err(expr.span, "cannot concatenate float literals");
+ Ok(ast::LitKind::Float(_, _)) => {
+ cx.span_err(span, "cannot concatenate float literals");
}
- ast::LitKind::Bool(_) => {
- cx.span_err(expr.span, "cannot concatenate boolean literals");
+ Ok(ast::LitKind::Bool(_)) => {
+ cx.span_err(span, "cannot concatenate boolean literals");
}
- ast::LitKind::Err => {}
- ast::LitKind::Int(_, _) if !is_nested => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+ Ok(ast::LitKind::Err) => {}
+ Ok(ast::LitKind::Int(_, _)) if !is_nested => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate numeric literals");
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try wrapping the number in an array",
format!("[{}]", snippet),
Applicability::MachineApplicable,
@@ -55,17 +59,20 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
}
err.emit();
}
- ast::LitKind::Int(
+ Ok(ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
- ) => {
+ )) => {
assert!(val > u8::MAX.into()); // must be an error
- cx.span_err(expr.span, "numeric literal is out of bounds");
+ cx.span_err(span, "numeric literal is out of bounds");
+ }
+ Ok(ast::LitKind::Int(_, _)) => {
+ cx.span_err(span, "numeric literal is not a `u8`");
}
- ast::LitKind::Int(_, _) => {
- cx.span_err(expr.span, "numeric literal is not a `u8`");
+ Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(),
+ Err(err) => {
+ report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
}
- _ => unreachable!(),
}
}
@@ -83,14 +90,14 @@ fn handle_array_element(
*has_errors = true;
None
}
- ast::ExprKind::Lit(ref lit) => match lit.kind {
- ast::LitKind::Int(
+ 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 <= u8::MAX.into() => Some(val as u8),
+ )) if val <= u8::MAX.into() => Some(val as u8),
- ast::LitKind::Byte(val) => Some(val),
- ast::LitKind::ByteStr(_) => {
+ Ok(ast::LitKind::Byte(val)) => Some(val),
+ Ok(ast::LitKind::ByteStr(_)) => {
if !*has_errors {
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
.note("byte strings are treated as arrays of bytes")
@@ -102,12 +109,22 @@ fn handle_array_element(
}
_ => {
if !*has_errors {
- invalid_type_err(cx, expr, true);
+ invalid_type_err(cx, token_lit, expr.span, true);
}
*has_errors = true;
None
}
},
+ ast::ExprKind::IncludedBytes(..) => {
+ if !*has_errors {
+ cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
+ .note("byte strings are treated as arrays of bytes")
+ .help("try flattening the array")
+ .emit();
+ }
+ *has_errors = true;
+ None
+ }
_ => {
missing_literals.push(expr.span);
None
@@ -127,8 +144,8 @@ pub fn expand_concat_bytes(
let mut missing_literals = vec![];
let mut has_errors = false;
for e in es {
- match e.kind {
- ast::ExprKind::Array(ref exprs) => {
+ 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)
@@ -137,10 +154,10 @@ pub fn expand_concat_bytes(
}
}
}
- ast::ExprKind::Repeat(ref expr, ref count) => {
- if let ast::ExprKind::Lit(ast::Lit {
- kind: ast::LitKind::Int(count_val, _), ..
- }) = count.value.kind
+ ast::ExprKind::Repeat(expr, count) => {
+ if let ast::ExprKind::Lit(token_lit) = count.value.kind
+ && let Ok(ast::LitKind::Int(count_val, _)) =
+ ast::LitKind::from_token_lit(token_lit)
{
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
@@ -153,20 +170,23 @@ pub fn expand_concat_bytes(
cx.span_err(count.value.span, "repeat count is not a positive number");
}
}
- ast::ExprKind::Lit(ref lit) => match lit.kind {
- ast::LitKind::Byte(val) => {
+ &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Byte(val)) => {
accumulator.push(val);
}
- ast::LitKind::ByteStr(ref bytes) => {
+ Ok(ast::LitKind::ByteStr(ref bytes)) => {
accumulator.extend_from_slice(&bytes);
}
_ => {
if !has_errors {
- invalid_type_err(cx, &e, false);
+ invalid_type_err(cx, token_lit, e.span, false);
}
has_errors = true;
}
},
+ ast::ExprKind::IncludedBytes(bytes) => {
+ accumulator.extend_from_slice(bytes);
+ }
ast::ExprKind::Err => {
has_errors = true;
}