compiler (attributes)
Rust currently has an attribute usage lint but it does not work particularly well. This RFC proposes a new implementation strategy that should make it significantly more useful.
The current implementation has two major issues:
#[deriving(Clone)]; // Shouldn't have put a ; here
struct Foo;
#[ignore(attribute-usage)] // Should have used #[allow(attribute-usage)] instead!
mod bar {
//...
}
ItemDecorators
can now be defined outside of the compiler, and there's no
way to tag them and associated attributes as valid. Something like this
requires an #[allow(attribute-usage)]
:#[feature(phase)];
#[phase(syntax, link)]
extern crate some_orm;
#[ormify]
pub struct Foo {
#[column(foo_)]
#[primary_key]
foo: int
}
The current implementation is implemented as a simple fold over the AST, comparing attributes against a whitelist. Crate-level attributes use a separate whitelist, but no other distinctions are made.
This RFC would change the implementation to actually track which attributes are
used during the compilation process. syntax::ast::Attribute_
would be
modified to add an ID field:
pub struct AttrId(uint);
pub struct Attribute_ {
id: AttrId,
style: AttrStyle,
value: @MetaItem,
is_sugared_doc: bool,
}
syntax::ast::parse::ParseSess
will generate new AttrId
s on demand. I
believe that attributes will only be created during parsing and expansion, and
the ParseSess
is accessible in both.
The AttrId
s will be used to create a side table of used attributes. This will
most likely be a thread local to make it easily accessible during all stages of
compilation by calling a function in syntax::attr
:
fn mark_used(attr: &Attribute) { }
The attribute-usage
lint would run at the end of compilation and warn on all
attributes whose ID does not appear in the side table.
One interesting edge case is attributes like doc
that are used, but not in
the normal compilation process. There could either be a separate fold pass to
mark all doc
attributes as used or doc
could simply be whitelisted in the
attribute-usage
lint.
Attributes in code that has been eliminated with #[cfg()]
will not be linted,
but I feel that this is consistent with the way #[cfg()]
works in general
(e.g. the code won't be type-checked either).
An alternative would be to rewrite rustc::middle::lint
to robustly check
that attributes are used where they're supposed to be. This will be fairly
complex and be prone to failure if/when more nodes are added to the AST. This
also doesn't solve motivation #2, which would require externally loaded lint
support.
#[phase(syntax)]
crate loading infrastructure could
be extended to pull a list of attributes from crates to use in the lint pass,
but I'm not sure if the extra complexity is worth it.