Skip to content

Commit 57b6ffc

Browse files
committed
Merge remote-tracking branch 'SergioBenitez/master'
2 parents 4ad2de6 + e7c214f commit 57b6ffc

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

text/0000-attributes-with-literals.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
- Feature Name: attributes_with_literals
2+
- Start Date: 2016-03-28
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
This RFC proposes accepting literals in attributes by defining the grammar of attributes as:
10+
11+
```ebnf
12+
attr : '#' '!'? '[' meta_item ']' ;
13+
14+
meta_item : IDENT ( '=' LIT | '(' meta_item_inner? ')' )? ;
15+
16+
meta_item_inner : (meta_item | LIT) (',' meta_item_inner)? ;
17+
```
18+
19+
Note that `LIT` is a valid Rust literal and `IDENT` is a valid Rust identifier. The following
20+
attributes, among others, would be accepted by this grammar:
21+
22+
```rust
23+
#[attr]
24+
#[attr(true)]
25+
#[attr(ident)]
26+
#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
27+
#[attr(100)]
28+
#[attr(enabled = true)]
29+
#[enabled(true)]
30+
#[attr("hello")]
31+
#[repr(C, align = 4)]
32+
#[repr(C, align(4))]
33+
```
34+
35+
# Motivation
36+
[motivation]: #motivation
37+
38+
At present, literals are only accepted as the value of a key-value pair in attributes. What's more,
39+
only _string_ literals are accepted. This means that literals can only appear in forms of
40+
`#[attr(name = "value")]` or `#[attr = "value"]`.
41+
42+
This forces non-string literal values to be awkwardly stringified. For example, while it is clear
43+
that something like alignment should be an integer value, the following are disallowed:
44+
`#[align(4)]`, `#[align = 4]`. Instead, we must use something akin to `#[align = "4"]`. Even
45+
`#[align("4")]` and `#[name("name")]` are disallowed, forcing key-value pairs or identifiers to be
46+
used instead: `#[align(size = "4")]` or `#[name(name)]`.
47+
48+
In short, the current design forces users to use values of a single type, and thus occasionally the
49+
_wrong_ type, in attributes.
50+
51+
### Cleaner Attributes
52+
53+
Implementation of this RFC can clean up the following attributes in the standard library:
54+
55+
* `#![recursion_limit = "64"]` **=>** `#![recursion_limit = 64]` or `#![recursion_limit(64)]`
56+
* `#[cfg(all(unix, target_pointer_width = "32"))]` **=>** `#[cfg(all(unix, target_pointer_width = 32))]`
57+
58+
If `align` were to be added as an attribute, the following are now valid options for its syntax:
59+
60+
* `#[repr(align(4))]`
61+
* `#[repr(align = 4)]`
62+
* `#[align = 4]`
63+
* `#[align(4)]`
64+
65+
### Syntax Extensions
66+
67+
As syntax extensions mature and become more widely used, being able to use literals in a variety of
68+
positions becomes more important.
69+
70+
# Detailed design
71+
[design]: #detailed-design
72+
73+
To clarify, _literals_ are:
74+
75+
* **Strings:** `"foo"`, `r##"foo"##`
76+
* **Byte Strings:** `b"foo"`
77+
* **Byte Characters:** `b'f'`
78+
* **Characters:** `'a'`
79+
* **Integers:** `1`, `1{i,u}{8,16,32,64,size}`
80+
* **Floats:** `1.0`, `1.0f{32,64}`
81+
* **Booleans:** `true`, `false`
82+
83+
They are defined in the [manual] and by implementation in the [AST].
84+
85+
[manual]: https://doc.rust-lang.org/reference.html#literals
86+
[AST]: http://manishearth.github.io/rust-internals-docs/syntax/ast/enum.LitKind.html
87+
88+
Implementation of this RFC requires the following changes:
89+
90+
1. The `MetaItemKind` structure would need to allow literals as top-level entities:
91+
92+
```rust
93+
pub enum MetaItemKind {
94+
Word(InternedString),
95+
List(InternedString, Vec<P<MetaItem>>),
96+
NameValue(InternedString, Lit),
97+
Literal(Lit),
98+
}
99+
```
100+
101+
2. `libsyntax` (`libsyntax/parse/attr.rs`) would need to be modified to allow literals as values in
102+
k/v pairs and as top-level entities of a list.
103+
104+
3. Crate metadata encoding/decoding would need to encode and decode literals in attributes.
105+
106+
# Drawbacks
107+
[drawbacks]: #drawbacks
108+
109+
This RFC requires a change to the AST and is likely to break syntax extensions using attributes in
110+
the wild.
111+
112+
# Alternatives
113+
[alternatives]: #alternatives
114+
115+
### Token trees
116+
117+
An alternative is to allow any tokens inside of an attribute. That is, the grammar could be:
118+
119+
```ebnf
120+
attr : '#' '!'? '[' TOKEN+ ']' ;
121+
```
122+
123+
where `TOKEN` is any valid Rust token. The drawback to this approach is that attributes lose any
124+
sense of structure. This results in more difficult and verbose attribute parsing, although this
125+
could be ameliorated through libraries. Further, this would require almost all of the existing
126+
attribute parsing code to change.
127+
128+
The advantage, of course, is that it allows any syntax and is rather future proof. It is also more
129+
inline with `macro!`s.
130+
131+
### Allow only unsuffixed literals
132+
133+
This RFC proposes allowing _any_ valid Rust literals in attributes. Instead, the use of literals
134+
could be restricted to only those that are unsuffixed. That is, only the following literals could be
135+
allowed:
136+
137+
* **Strings:** `"foo"`
138+
* **Characters:** `'a'`
139+
* **Integers:** `1`
140+
* **Floats:** `1.0`
141+
* **Booleans:** `true`, `false`
142+
143+
This cleans up the appearance of attributes will still increasing flexibility.
144+
145+
### Allow literals only as values in k/v pairs
146+
147+
Instead of allowing literals in top-level positions, i.e. `#[attr(4)]`, only allow them as values in
148+
key value pairs: `#[attr = 4]` or `#[attr(ident = 4)]`. This has the nice advantage that it was the
149+
initial idea for attributes, and so the AST types already reflect this. As such, no changes would
150+
have to be made to existing code. The drawback, of course, is the lack of flexibility. `#[repr(C,
151+
align(4))]` would no longer be valid.
152+
153+
### Do nothing
154+
155+
Of course, the current design could be kept. Although it seems that the initial intention was for a
156+
form of literals to be allowed. Unfortunately, this idea was [scrapped due to release pressure] and
157+
never revisited. Even [the reference] alludes to allowing all literals as values in k/v pairs.
158+
159+
[scrapped due to release pressure]: https://github.com/rust-lang/rust/issues/623
160+
[the reference]: https://doc.rust-lang.org/reference.html#attributes
161+
162+
# Unresolved questions
163+
[unresolved]: #unresolved-questions
164+
165+
None that I can think of.

0 commit comments

Comments
 (0)