9
9
This RFC proposes accepting literals in attributes by defining the grammar of attributes as:
10
10
11
11
``` ebnf
12
- attr : '#' '[' meta_item ']' ;
12
+ attr : '#' '!'? ' [' meta_item ']' ;
13
13
14
14
meta_item : IDENT ( '=' LIT | '(' meta_item_inner? ')' )? ;
15
15
@@ -21,10 +21,12 @@ attributes, among others, would be accepted by this grammar:
21
21
22
22
``` rust
23
23
#[attr]
24
- #[attr()]
24
+ #[attr(true )]
25
25
#[attr(ident)]
26
- #[attr(ident, ident = 100, ident = " hello" , ident(100))]
26
+ #[attr(ident, 100, true, " true " , ident = 100, ident = " hello" , ident(100))]
27
27
#[attr(100)]
28
+ #[attr(enabled = true)]
29
+ #[enabled(true)]
28
30
#[attr(" hello" )]
29
31
#[repr(C , align = 4)]
30
32
#[repr(C , align(4))]
@@ -40,10 +42,11 @@ only _string_ literals are accepted. This means that literals can only appear in
40
42
This forces non-string literal values to be awkwardly stringified. For example, while it is clear
41
43
that something like alignment should be an integer value, the following are disallowed:
42
44
` #[align(4)] ` , ` #[align = 4] ` . Instead, we must use something akin to ` #[align = "4"] ` . Even
43
- ` #[align("4")] ` and ` #[name("name")] ` are disallowed, forcing identifiers or key-values to be used
44
- instead: ` #[align(size = "4")] ` or ` #[name(name)] ` .
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)] ` .
45
47
46
- In short, the current design forces users to use values of the wrong type in attributes.
48
+ In short, the current design forces users to use values of a single type, and thus occasionally the
49
+ _ wrong_ type, in attributes.
47
50
48
51
### Cleaner Attributes
49
52
@@ -67,14 +70,31 @@ positions becomes more important.
67
70
# Detailed design
68
71
[ design ] : #detailed-design
69
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
+
70
90
1 . The ` MetaItemKind ` structure would need to allow literals as top-level entities:
71
91
72
92
``` rust
73
93
pub enum MetaItemKind {
74
94
Word (InternedString ),
75
95
List (InternedString , Vec <P <MetaItem >>),
76
96
NameValue (InternedString , Lit ),
77
- Lit ,
97
+ Literal ( Lit ) ,
78
98
}
79
99
```
80
100
@@ -92,12 +112,12 @@ the wild.
92
112
# Alternatives
93
113
[alternatives ]: #alternatives
94
114
95
- ### Token Trees
115
+ ### Token trees
96
116
97
117
An alternative is to allow any tokens inside of an attribute . That is , the grammar could be :
98
118
99
119
```ebnf
100
- attr : '#' '[' TOKEN + ']' ;
120
+ attr : '#' '!' ? ' [' TOKEN + ']' ;
101
121
```
102
122
103
123
where ` TOKEN ` is any valid Rust token. The drawback to this approach is that attributes lose any
@@ -108,21 +128,36 @@ attribute parsing code to change.
108
128
The advantage, of course, is that it allows any syntax and is rather future proof. It is also more
109
129
inline with ` macro! ` s.
110
130
111
- ### Only Allow Literals as Values in K/V Pairs
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
112
146
113
147
Instead of allowing literals in top-level positions, i.e. ` #[attr(4)] ` , only allow them as values in
114
148
key value pairs: ` #[attr = 4] ` or ` #[attr(ident = 4)] ` . This has the nice advantage that it was the
115
149
initial idea for attributes, and so the AST types already reflect this. As such, no changes would
116
150
have to be made to existing code. The drawback, of course, is the lack of flexibility. `#[ repr(C,
117
151
align(4))] ` would no longer be valid.
118
152
119
- ### Do Nothing
153
+ ### Do nothing
120
154
121
155
Of course, the current design could be kept. Although it seems that the initial intention was for a
122
156
form of literals to be allowed. Unfortunately, this idea was [ scrapped due to release pressure] and
123
- never revisited. Even the manual alludes to allowing all literals.
157
+ never revisited. Even [ the reference ] alludes to allowing all literals as values in k/v pairs .
124
158
125
159
[ scrapped due to release pressure ] : https://github.com/rust-lang/rust/issues/623
160
+ [ the manual ] : https://doc.rust-lang.org/reference.html#attributes
126
161
127
162
# Unresolved questions
128
163
[ unresolved ] : #unresolved-questions
0 commit comments