Skip to content

Commit 3173151

Browse files
committed
Support [x; n] expressions in concat_bytes!
Contributes to rust-lang#87555.
1 parent 7abab1e commit 3173151

File tree

4 files changed

+135
-42
lines changed

4 files changed

+135
-42
lines changed

Diff for: compiler/rustc_builtin_macros/src/concat_bytes.rs

+65-40
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,52 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
7272
}
7373
}
7474

75+
fn handle_array_element(
76+
cx: &mut base::ExtCtxt<'_>,
77+
has_errors: &mut bool,
78+
missing_literals: &mut Vec<rustc_span::Span>,
79+
expr: &P<rustc_ast::Expr>,
80+
) -> Option<u8> {
81+
match expr.kind {
82+
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
83+
if !*has_errors {
84+
cx.span_err(expr.span, "cannot concatenate doubly nested array");
85+
}
86+
*has_errors = true;
87+
None
88+
}
89+
ast::ExprKind::Lit(ref lit) => match lit.kind {
90+
ast::LitKind::Int(
91+
val,
92+
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
93+
) if val <= u8::MAX.into() => Some(val as u8),
94+
95+
ast::LitKind::Byte(val) => Some(val),
96+
ast::LitKind::ByteStr(_) => {
97+
if !*has_errors {
98+
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
99+
.note("byte strings are treated as arrays of bytes")
100+
.help("try flattening the array")
101+
.emit();
102+
}
103+
*has_errors = true;
104+
None
105+
}
106+
_ => {
107+
if !*has_errors {
108+
invalid_type_err(cx, expr, true);
109+
}
110+
*has_errors = true;
111+
None
112+
}
113+
},
114+
_ => {
115+
missing_literals.push(expr.span);
116+
None
117+
}
118+
}
119+
}
120+
75121
pub fn expand_concat_bytes(
76122
cx: &mut base::ExtCtxt<'_>,
77123
sp: rustc_span::Span,
@@ -88,48 +134,27 @@ pub fn expand_concat_bytes(
88134
match e.kind {
89135
ast::ExprKind::Array(ref exprs) => {
90136
for expr in exprs {
91-
match expr.kind {
92-
ast::ExprKind::Array(_) => {
93-
if !has_errors {
94-
cx.span_err(expr.span, "cannot concatenate doubly nested array");
95-
}
96-
has_errors = true;
97-
}
98-
ast::ExprKind::Lit(ref lit) => match lit.kind {
99-
ast::LitKind::Int(
100-
val,
101-
ast::LitIntType::Unsuffixed
102-
| ast::LitIntType::Unsigned(ast::UintTy::U8),
103-
) if val <= u8::MAX.into() => {
104-
accumulator.push(val as u8);
105-
}
106-
107-
ast::LitKind::Byte(val) => {
108-
accumulator.push(val);
109-
}
110-
ast::LitKind::ByteStr(_) => {
111-
if !has_errors {
112-
cx.struct_span_err(
113-
expr.span,
114-
"cannot concatenate doubly nested array",
115-
)
116-
.note("byte strings are treated as arrays of bytes")
117-
.help("try flattening the array")
118-
.emit();
119-
}
120-
has_errors = true;
121-
}
122-
_ => {
123-
if !has_errors {
124-
invalid_type_err(cx, expr, true);
125-
}
126-
has_errors = true;
127-
}
128-
},
129-
_ => {
130-
missing_literals.push(expr.span);
137+
if let Some(elem) =
138+
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
139+
{
140+
accumulator.push(elem);
141+
}
142+
}
143+
}
144+
ast::ExprKind::Repeat(ref expr, ref count) => {
145+
if let ast::ExprKind::Lit(ast::Lit {
146+
kind: ast::LitKind::Int(count_val, _), ..
147+
}) = count.value.kind
148+
{
149+
if let Some(elem) =
150+
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
151+
{
152+
for _ in 0..count_val {
153+
accumulator.push(elem);
131154
}
132155
}
156+
} else {
157+
cx.span_err(count.value.span, "repeat count is not a number");
133158
}
134159
}
135160
ast::ExprKind::Lit(ref lit) => match lit.kind {

Diff for: src/test/ui/macros/concat-bytes-error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,12 @@ fn main() {
3939
]);
4040
concat_bytes!(5u16); //~ ERROR cannot concatenate numeric literals
4141
concat_bytes!([5u16]); //~ ERROR numeric literal is not a `u8`
42+
concat_bytes!([3; ()]); //~ ERROR repeat count is not a number
43+
concat_bytes!([3; -2]); //~ ERROR repeat count is not a number
44+
concat_bytes!([pie; -2]); //~ ERROR repeat count is not a number
45+
concat_bytes!([pie; 2]); //~ ERROR expected a byte literal
46+
concat_bytes!([2.2; 0]); //~ ERROR cannot concatenate float literals
47+
concat_bytes!([5.5; ()]); //~ ERROR repeat count is not a number
48+
concat_bytes!([[1, 2, 3]; 3]); //~ ERROR cannot concatenate doubly nested array
49+
concat_bytes!([[42; 2]; 3]); //~ ERROR cannot concatenate doubly nested array
4250
}

Diff for: src/test/ui/macros/concat-bytes-error.stderr

+51-1
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,55 @@ error: numeric literal is not a `u8`
127127
LL | concat_bytes!([5u16]);
128128
| ^^^^
129129

130-
error: aborting due to 20 previous errors
130+
error: repeat count is not a number
131+
--> $DIR/concat-bytes-error.rs:42:23
132+
|
133+
LL | concat_bytes!([3; ()]);
134+
| ^^
135+
136+
error: repeat count is not a number
137+
--> $DIR/concat-bytes-error.rs:43:23
138+
|
139+
LL | concat_bytes!([3; -2]);
140+
| ^^
141+
142+
error: repeat count is not a number
143+
--> $DIR/concat-bytes-error.rs:44:25
144+
|
145+
LL | concat_bytes!([pie; -2]);
146+
| ^^
147+
148+
error: expected a byte literal
149+
--> $DIR/concat-bytes-error.rs:45:20
150+
|
151+
LL | concat_bytes!([pie; 2]);
152+
| ^^^
153+
|
154+
= note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
155+
156+
error: cannot concatenate float literals
157+
--> $DIR/concat-bytes-error.rs:46:20
158+
|
159+
LL | concat_bytes!([2.2; 0]);
160+
| ^^^
161+
162+
error: repeat count is not a number
163+
--> $DIR/concat-bytes-error.rs:47:25
164+
|
165+
LL | concat_bytes!([5.5; ()]);
166+
| ^^
167+
168+
error: cannot concatenate doubly nested array
169+
--> $DIR/concat-bytes-error.rs:48:20
170+
|
171+
LL | concat_bytes!([[1, 2, 3]; 3]);
172+
| ^^^^^^^^^
173+
174+
error: cannot concatenate doubly nested array
175+
--> $DIR/concat-bytes-error.rs:49:20
176+
|
177+
LL | concat_bytes!([[42; 2]; 3]);
178+
| ^^^^^^^
179+
180+
error: aborting due to 28 previous errors
131181

Diff for: src/test/ui/macros/concat-bytes.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,15 @@
33

44
fn main() {
55
assert_eq!(concat_bytes!(), &[]);
6-
assert_eq!(concat_bytes!(b'A', b"BC", [68, b'E', 70]), b"ABCDEF");
6+
assert_eq!(
7+
concat_bytes!(b'A', b"BC", [68, b'E', 70], [b'G'; 1], [72; 2], [73u8; 3], [65; 0]),
8+
b"ABCDEFGHHIII",
9+
);
10+
assert_eq!(
11+
concat_bytes!(
12+
concat_bytes!(b"AB", b"CD"),
13+
concat_bytes!(b"EF", b"GH"),
14+
),
15+
b"ABCDEFGH",
16+
);
717
}

0 commit comments

Comments
 (0)