Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b2da155

Browse files
committed
Introduce ExprKind::IncludedBytes
1 parent b7b7f27 commit b2da155

File tree

19 files changed

+78
-15
lines changed

19 files changed

+78
-15
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ impl Expr {
12081208
ExprKind::Tup(_) => ExprPrecedence::Tup,
12091209
ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
12101210
ExprKind::Unary(..) => ExprPrecedence::Unary,
1211-
ExprKind::Lit(_) => ExprPrecedence::Lit,
1211+
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) => ExprPrecedence::Lit,
12121212
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
12131213
ExprKind::Let(..) => ExprPrecedence::Let,
12141214
ExprKind::If(..) => ExprPrecedence::If,
@@ -1446,6 +1446,12 @@ pub enum ExprKind {
14461446
/// with an optional value to be returned.
14471447
Yeet(Option<P<Expr>>),
14481448

1449+
/// Bytes included via `include_bytes!`
1450+
/// Added for optimization purposes to avoid the need to escape
1451+
/// large binary blobs - should always behave like [`ExprKind::Lit`]
1452+
/// with a `ByteStr` literal.
1453+
IncludedBytes(Lrc<[u8]>),
1454+
14491455
/// Placeholder for an expression that wasn't syntactically well formed in some way.
14501456
Err,
14511457
}

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
14281428
}
14291429
ExprKind::Try(expr) => vis.visit_expr(expr),
14301430
ExprKind::TryBlock(body) => vis.visit_block(body),
1431-
ExprKind::Lit(_) | ExprKind::Err => {}
1431+
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {}
14321432
}
14331433
vis.visit_id(id);
14341434
vis.visit_span(span);

compiler/rustc_ast/src/util/literal.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::ast::{self, Lit, LitKind};
44
use crate::token::{self, Token};
5+
use rustc_data_structures::sync::Lrc;
56
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
67
use rustc_span::symbol::{kw, sym, Symbol};
78
use rustc_span::Span;
@@ -231,6 +232,13 @@ impl Lit {
231232
Lit { token_lit: kind.to_token_lit(), kind, span }
232233
}
233234

235+
/// Recovers an AST literal from a string of bytes produced by `include_bytes!`.
236+
/// This requires ASCII-escaping the string, which can result in poor performance
237+
/// for very large strings of bytes.
238+
pub fn from_included_bytes(bytes: &Lrc<[u8]>, span: Span) -> Lit {
239+
Self::from_lit_kind(LitKind::ByteStr(bytes.clone()), span)
240+
}
241+
234242
/// Losslessly convert an AST literal into a token.
235243
pub fn to_token(&self) -> Token {
236244
let kind = match self.token_lit.kind {

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
901901
}
902902
ExprKind::Try(ref subexpression) => visitor.visit_expr(subexpression),
903903
ExprKind::TryBlock(ref body) => visitor.visit_block(body),
904-
ExprKind::Lit(_) | ExprKind::Err => {}
904+
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {}
905905
}
906906

907907
visitor.visit_expr_post(expression)

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
8787
ExprKind::Lit(ref l) => {
8888
hir::ExprKind::Lit(respan(self.lower_span(l.span), l.kind.clone()))
8989
}
90+
ExprKind::IncludedBytes(ref bytes) => hir::ExprKind::Lit(respan(
91+
self.lower_span(e.span),
92+
LitKind::ByteStr(bytes.clone()),
93+
)),
9094
ExprKind::Cast(ref expr, ref ty) => {
9195
let expr = self.lower_expr(expr);
9296
let ty =

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
323323
// ```
324324
fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> {
325325
match expr.kind {
326-
ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {}
326+
ExprKind::Lit(..)
327+
| ExprKind::ConstBlock(..)
328+
| ExprKind::IncludedBytes(..)
329+
| ExprKind::Err => {}
327330
ExprKind::Path(..) if allow_paths => {}
328331
ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
329332
_ => {

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ impl<'a> State<'a> {
322322
ast::ExprKind::Lit(ref lit) => {
323323
self.print_literal(lit);
324324
}
325+
ast::ExprKind::IncludedBytes(ref bytes) => {
326+
let lit = ast::Lit::from_included_bytes(bytes, expr.span);
327+
self.print_literal(&lit)
328+
}
325329
ast::ExprKind::Cast(ref expr, ref ty) => {
326330
let prec = AssocOp::As.precedence() as i8;
327331
self.print_expr_maybe_paren(expr, prec);

compiler/rustc_builtin_macros/src/assert/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
303303
| ExprKind::Field(_, _)
304304
| ExprKind::ForLoop(_, _, _, _)
305305
| ExprKind::If(_, _, _)
306+
| ExprKind::IncludedBytes(..)
306307
| ExprKind::InlineAsm(_)
307308
| ExprKind::Let(_, _, _)
308309
| ExprKind::Lit(_)

compiler/rustc_builtin_macros/src/concat.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ pub fn expand_concat(
4343
has_errors = true;
4444
}
4545
},
46+
ast::ExprKind::IncludedBytes(..) => {
47+
cx.span_err(e.span, "cannot concatenate a byte string literal")
48+
}
4649
ast::ExprKind::Err => {
4750
has_errors = true;
4851
}

compiler/rustc_builtin_macros/src/concat_bytes.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ fn handle_array_element(
108108
None
109109
}
110110
},
111+
ast::ExprKind::IncludedBytes(..) => {
112+
if !*has_errors {
113+
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
114+
.note("byte strings are treated as arrays of bytes")
115+
.help("try flattening the array")
116+
.emit();
117+
}
118+
*has_errors = true;
119+
None
120+
}
111121
_ => {
112122
missing_literals.push(expr.span);
113123
None
@@ -167,6 +177,9 @@ pub fn expand_concat_bytes(
167177
has_errors = true;
168178
}
169179
},
180+
ast::ExprKind::IncludedBytes(ref bytes) => {
181+
accumulator.extend_from_slice(bytes);
182+
}
170183
ast::ExprKind::Err => {
171184
has_errors = true;
172185
}

0 commit comments

Comments
 (0)