Skip to content

Commit 1245e64

Browse files
sfackleralexcrichton
authored andcommitted
RFC: Rearchitect the attribute-usage lint
1 parent a260073 commit 1245e64

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

active/0002-attribute-usage.md

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
- Start Date: 2012-03-20
2+
- RFC PR #: 3
3+
- Rust Issue #: TBD
4+
5+
# Summary
6+
7+
Rust currently has an attribute usage lint but it does not work particularly
8+
well. This RFC proposes a new implementation strategy that should make it
9+
significantly more useful.
10+
11+
# Motivation
12+
13+
The current implementation has two major issues:
14+
15+
+ There are very limited warnings for valid attributes that end up in the
16+
wrong place. Something like this will be silently ignored:
17+
```rust
18+
#[deriving(Clone)]; // Shouldn't have put a ; here
19+
struct Foo;
20+
21+
#[ignore(attribute-usage)] // Should have used #[allow(attribute-usage)] instead!
22+
mod bar {
23+
//...
24+
}
25+
```
26+
+ `ItemDecorators` can now be defined outside of the compiler, and there's no
27+
way to tag them and associated attributes as valid. Something like this
28+
requires an `#[allow(attribute-usage)]`:
29+
```rust
30+
#[feature(phase)];
31+
#[phase(syntax, link)]
32+
extern crate some_orm;
33+
34+
#[ormify]
35+
pub struct Foo {
36+
#[column(foo_)]
37+
#[primary_key]
38+
foo: int
39+
}
40+
```
41+
42+
# Detailed design
43+
44+
The current implementation is implemented as a simple fold over the AST,
45+
comparing attributes against a whitelist. Crate-level attributes use a separate
46+
whitelist, but no other distinctions are made.
47+
48+
This RFC would change the implementation to actually track which attributes are
49+
used during the compilation process. `syntax::ast::Attribute_` would be
50+
modified to add an ID field:
51+
```rust
52+
pub struct AttrId(uint);
53+
54+
pub struct Attribute_ {
55+
id: AttrId,
56+
style: AttrStyle,
57+
value: @MetaItem,
58+
is_sugared_doc: bool,
59+
}
60+
```
61+
62+
`syntax::ast::parse::ParseSess` will generate new `AttrId`s on demand. I
63+
believe that attributes will only be created during parsing and expansion, and
64+
the `ParseSess` is accessible in both.
65+
66+
The `AttrId`s will be used to create a side table of used attributes. This will
67+
most likely be a thread local to make it easily accessible during all stages of
68+
compilation by calling a function in `syntax::attr`:
69+
```rust
70+
fn mark_used(attr: &Attribute) { }
71+
```
72+
73+
The `attribute-usage` lint would run at the end of compilation and warn on all
74+
attributes whose ID does not appear in the side table.
75+
76+
One interesting edge case is attributes like `doc` that are used, but not in
77+
the normal compilation process. There could either be a separate fold pass to
78+
mark all `doc` attributes as used or `doc` could simply be whitelisted in the
79+
`attribute-usage` lint.
80+
81+
Attributes in code that has been eliminated with `#[cfg()]` will not be linted,
82+
but I feel that this is consistent with the way `#[cfg()]` works in general
83+
(e.g. the code won't be type-checked either).
84+
85+
# Alternatives
86+
87+
An alternative would be to rewrite `rustc::middle::lint` to robustly check
88+
that attributes are used where they're supposed to be. This will be fairly
89+
complex and be prone to failure if/when more nodes are added to the AST. This
90+
also doesn't solve motivation #2, which would require externally loaded lint
91+
support.
92+
93+
# Unresolved questions
94+
95+
+ This implementation doesn't allow for a distinction between "unused" and
96+
"unknown" attributes. The `#[phase(syntax)]` crate loading infrastructure could
97+
be extended to pull a list of attributes from crates to use in the lint pass,
98+
but I'm not sure if the extra complexity is worth it.
99+
+ The side table could be threaded through all of the compilation stages that
100+
need to use it instead of being a thread local. This would probably require
101+
significantly more work than the thread local approach, however. The thread
102+
local approach should not negatively impact any future parallelization work as
103+
each thread can keep its own side table, which can be merged into one for the
104+
lint pass.
105+

0 commit comments

Comments
 (0)