Summary

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.

Motivation

The current implementation

実装
has two major issues:

  • There are very limited warnings for valid
    有効な、正しい
    attributes that end up in the wrong place. Something like this will be silently ignored:
    無視する
#![allow(unused)] fn main() { #[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)]:
#![allow(unused)] fn main() { #[feature(phase)]; #[phase(syntax, link)] extern crate some_orm; #[ormify] pub struct Foo { #[column(foo_)] #[primary_key] foo: int } }

Detailed design
設計(する)

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:

#![allow(unused)] fn main() { pub struct AttrId(uint); pub struct Attribute_ { id: AttrId, style: AttrStyle, value: @MetaItem, is_sugared_doc: bool, } }

syntax::ast::parse::ParseSess will generate new AttrIds on demand. I believe that attributes will only be created during parsing

構文解析の
and expansion, and the ParseSess is accessible in both.

The AttrIds 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:

#![allow(unused)] fn main() { 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).

Alternatives

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.

Unresolved questions

  • This implementation
    実装
    doesn't allow
    許可する、可能にする
    for a distinction between "unused" and "unknown" attributes. The #[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.
  • The side table could be threaded through all of the compilation stages that need to use it instead of being a thread local. This would probably require significantly
    著しく
    more work than the thread local approach, however. The thread local approach should not negatively impact any future parallelization work as each thread can keep its own side table, which can be merged into one for the lint pass.