|
| 1 | +- Start Date: 2014-11-25 |
| 2 | +- RFC PR: |
| 3 | +- Rust Issue: |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +Change attribute syntax from `#[foo]` and `#![foo]` to `@foo` and `@!foo`. |
| 8 | + |
| 9 | +# Motivation |
| 10 | + |
| 11 | +Other languages like Java and Python use `@` for their equivalents of |
| 12 | +attributes. In addition, `@foo` is easier to type than `#[foo]`, and is |
| 13 | +arguably less noisy looking. |
| 14 | + |
| 15 | +This change was proposed as part of [RFC |
| 16 | +386](https://github.com/rust-lang/rfcs/pull/386/files) and was generally |
| 17 | +well-received. |
| 18 | + |
| 19 | +# Detailed design |
| 20 | + |
| 21 | +Attributes and inner attributes would be written in one of the following forms |
| 22 | +(BNF): |
| 23 | + |
| 24 | +``` |
| 25 | +ATTR = '@' [!] META |
| 26 | +META = ID |
| 27 | + | ID '(' META_SEQ ')' |
| 28 | +META_SEQ = META_ITEM {',' META_ITEM} |
| 29 | +META_ITEM = META |
| 30 | + | ID '=' STRING_LITERAL |
| 31 | +``` |
| 32 | + |
| 33 | +Here are some examples of legal syntax: |
| 34 | + |
| 35 | +* `@inline` |
| 36 | +* `@!inline` |
| 37 | +* `@deprecated(reason = "foo")` |
| 38 | +* `@deriving(Eq)` |
| 39 | + |
| 40 | +Note that some attributes which are legal today have no equivalent: |
| 41 | + |
| 42 | +* `#[deprecated = "foo"]` becomes `@deprecated(reason = "foo")` |
| 43 | + |
| 44 | +## Implementation |
| 45 | + |
| 46 | +The parser will be adjusted to accept `@`-attributes in addition to current |
| 47 | +attributes. The internal data structures will remain the same. Once a snapshot |
| 48 | +lands, the Rust codebase can be converted, and parsing support for |
| 49 | +`#`-attributes can be removed with an error message added explaining how to fix |
| 50 | +code. |
| 51 | + |
| 52 | +# Drawbacks |
| 53 | + |
| 54 | +It's a large change that will cause a ton of churn very close to 1.0. Since the |
| 55 | +only compiler changes required will be to the parser and pretty printer, it's |
| 56 | +relatively low risk (compared to resolve or typeck changes for example). |
| 57 | + |
| 58 | +# Alternatives |
| 59 | + |
| 60 | +We can punt on this until after 1.0. `@`-attributes and `#`-attributes will |
| 61 | +have to coexist to avoid breaking backwards compatibility, but that won't be |
| 62 | +all that hard to deal with. |
| 63 | + |
| 64 | +We can leave the syntax as is, which is also not that bad. |
| 65 | + |
| 66 | +Support for `#[deprecated = "reason"]` style attributes is removed because |
| 67 | +`@deprecated = "reason"` is a bit visually confusing since there are no |
| 68 | +delimiters wrapping the attribute. There are a couple of alternatives here. |
| 69 | +One is to just allow that syntax. It's not grammatically ambiguous, after all. |
| 70 | + |
| 71 | +Another is to change `foo = "bar'` to `foo("bar")`: |
| 72 | +``` |
| 73 | +ATTR = '@' [!] META |
| 74 | +META = ID |
| 75 | + | ID '(' STRING_LITERAL ') |
| 76 | + | ID '(' META_SEQ ')' |
| 77 | +META_SEQ = META {',' META} |
| 78 | +``` |
| 79 | + |
| 80 | +For example: |
| 81 | +* `@deprecated("foo")` |
| 82 | +* `@cfg(all(target_os("linux"), feature("my_cargo_feature")))` |
| 83 | + |
| 84 | +This allows for a more convenient syntax for deprecation, but does add even |
| 85 | +more parentheses to attribute invocations like the `cfg` example above. |
| 86 | + |
| 87 | +# Unresolved questions |
| 88 | + |
| 89 | +Should there be a "deprecation period" where the `#` syntax is accepted with a |
| 90 | +warning? |
0 commit comments