Skip to content

Commit ba2d9d7

Browse files
committed
RFC: Teach concat!() to join [u8] and byte str
1 parent 2d5218a commit ba2d9d7

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

text/0000-byte-concat.md

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
- Feature Name: byte_concat
2+
- Start Date: 2018-07-31
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Allow the use of `concat!()` to join byte sequences onto an `u8` array,
10+
beyond the current support for `str` literals.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
`concat!()` is convenient and useful to create compile time `str` literals
16+
from `str`, `bool`, numeric and `char` literals in the code. This RFC would
17+
expand this capability to produce `[u8]` instead of `str` when any of its
18+
arguments is a byte `str` or a byte `char`.
19+
20+
# Guide-level explanation
21+
[guide-level-explanation]: #guide-level-explanation
22+
23+
Whenever any of the arguments to `concat!()` is a byte literal, its output
24+
will be a byte literal, and the other arguments will be evaluated on their
25+
byte contents.
26+
27+
- `str`s and `char`s are evaluated in the same way as `String::as_bytes`,
28+
- `bool`s are not accepted, use a numeric literal instead,
29+
- numeric literals passed to `concat!()` must fit in `u8`, any number
30+
larger than `std::u8::MAX` causes a compile time error, like the
31+
following:
32+
```
33+
error: cannot concatenate a non-`u8` literal in a byte string literal
34+
--> $FILE:XX:YY
35+
|
36+
XX | concat!(256, b"val");
37+
| ^^^ this value is larger than `255`
38+
```
39+
- numeric array literals that can be coerced to `[u8]` are accepted, if the
40+
literals are outside of `u8` range, it will cause a compile time error:
41+
```
42+
error: cannot concatenate a non-`u8` literal in a byte string literal
43+
--> $FILE:XX:YY
44+
|
45+
XX | concat!([300, 1, 2, 256], b"val");
46+
| ^^^ ^^^ this value is larger than `255`
47+
| |
48+
| this value is larger than `255`
49+
```
50+
51+
For example, `concat!(42, b"va", b'l', [1, 2])` evaluates to
52+
`[42, 118, 97, 108, 1, 2]`.
53+
54+
# Reference-level explanation
55+
[reference-level-explanation]: #reference-level-explanation
56+
57+
[PR #52838](https://github.com/rust-lang/rust/pull/52838) lays the
58+
foundation for the implementation of the full RFC.
59+
60+
This new feature could be surprising when editting existing code, if
61+
`concat!("foo", `b`, `a`, `r`, 3)` were changed to
62+
`concat!("foo", `b`, b`a`, `r`, 3)`, as the macro call would change from
63+
being evaluated as a `str` literal "foobar3" to `[u8]`
64+
`[102, 111, 111, 98, 97, 114, 3]`.
65+
66+
# Drawbacks
67+
[drawbacks]: #drawbacks
68+
69+
As mentioned in the previous section, this causes `concat!()`'s output to be
70+
dependant on its input.
71+
72+
# Rationale and alternatives
73+
[rationale-and-alternatives]: #rationale-and-alternatives
74+
75+
A new macro `bconcat!()` could be introduced instead. People in the wild
76+
have already intended to use `concat!()` for byte literals. A new macro
77+
could be explained to users through diagnostics, but using the existing
78+
macro adds support for something that a user could expect to work.
79+
80+
# Prior art
81+
[prior-art]: #prior-art
82+
83+
[PR #52838](https://github.com/rust-lang/rust/pull/52838) lays the
84+
foundation for the implementation of the full RFC, trying to enable a real
85+
use seen in the wild.
86+
87+
# Unresolved questions
88+
[unresolved-questions]: #unresolved-questions
89+
90+
- What parts of the design do you expect to resolve through the RFC process before this gets merged?
91+
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
92+
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?

0 commit comments

Comments
 (0)