diff --git a/0000-attribute-usage.md b/0000-attribute-usage.md
new file mode 100644
index 00000000000..d5158f4ac7a
--- /dev/null
+++ b/0000-attribute-usage.md
@@ -0,0 +1,101 @@
+# 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:
+```rust
+#[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)]`:
+```rust
+#[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:
+```rust
+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`:
+```rust
+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.
+