From c305473d3c60d5b4590ef8c715468f718a7aad8f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 20 May 2014 00:07:24 -0700 Subject: [PATCH 1/6] Add AttrId to Attribute_ --- src/librustc/back/svh.rs | 7 ++++- src/librustc/front/std_inject.rs | 11 ++++--- src/librustc/front/test.rs | 3 +- src/librustc/metadata/decoder.rs | 1 + src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/trans/base.rs | 5 +-- src/libsyntax/ast.rs | 4 +++ src/libsyntax/attr.rs | 36 ++++++++++++++++++---- src/libsyntax/ext/build.rs | 6 ++-- src/libsyntax/ext/deriving/clone.rs | 3 +- src/libsyntax/ext/deriving/cmp/eq.rs | 3 +- src/libsyntax/ext/deriving/cmp/ord.rs | 3 +- src/libsyntax/ext/deriving/cmp/totaleq.rs | 5 +-- src/libsyntax/ext/deriving/cmp/totalord.rs | 3 +- src/libsyntax/ext/deriving/default.rs | 3 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 ++ src/libsyntax/ext/deriving/hash.rs | 3 +- src/libsyntax/ext/deriving/primitive.rs | 3 +- src/libsyntax/ext/deriving/zero.rs | 3 +- src/libsyntax/ext/expand.rs | 2 ++ src/libsyntax/ext/format.rs | 7 +++-- src/libsyntax/fold.rs | 1 + src/libsyntax/parse/attr.rs | 8 ++++- 23 files changed, 94 insertions(+), 30 deletions(-) diff --git a/src/librustc/back/svh.rs b/src/librustc/back/svh.rs index 489722aa13f..9ad653498ba 100644 --- a/src/librustc/back/svh.rs +++ b/src/librustc/back/svh.rs @@ -91,7 +91,12 @@ pub fn calculate(krate: &ast::Crate) -> Svh { // types and then use hash_content. But, since all crate // attributes should appear near beginning of the file, it is // not such a big deal to be sensitive to their spans for now. - krate.attrs.hash(&mut state); + // + // We hash only the MetaItems instead of the entire Attribute + // to avoid hashing the AttrId + for attr in krate.attrs.iter() { + attr.node.value.hash(&mut state); + } let hash = state.result(); return Svh { diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index efaeeaa5575..e380af7a4f0 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -78,7 +78,7 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { with_version("std"), ast::DUMMY_NODE_ID), attrs: vec!( - attr::mk_attr_outer(attr::mk_list_item( + attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item( InternedString::new("phase"), vec!( attr::mk_word_item(InternedString::new("syntax")), @@ -110,7 +110,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // Add it during the prelude injection instead. // Add #![feature(phase)] here, because we use #[phase] on extern crate std. - let feat_phase_attr = attr::mk_attr_inner(attr::mk_list_item( + let feat_phase_attr = attr::mk_attr_inner(attr::mk_attr_id(), + attr::mk_list_item( InternedString::new("feature"), vec![attr::mk_word_item(InternedString::new("phase"))], )); @@ -138,7 +139,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // This must happen here and not in StandardLibraryInjector because this // fold happens second. - let no_std_attr = attr::mk_attr_inner(attr::mk_word_item(InternedString::new("no_std"))); + let no_std_attr = attr::mk_attr_inner(attr::mk_attr_id(), + attr::mk_word_item(InternedString::new("no_std"))); krate.attrs.push(no_std_attr); if !no_prelude(krate.attrs.as_slice()) { @@ -146,7 +148,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // `#![no_implicit_prelude]` at the crate level. // fold_mod() will insert glob path. - let globs_attr = attr::mk_attr_inner(attr::mk_list_item( + let globs_attr = attr::mk_attr_inner(attr::mk_attr_id(), + attr::mk_list_item( InternedString::new("feature"), vec!( attr::mk_word_item(InternedString::new("globs")), diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index e7a5aeb9ef5..d5e9192cd74 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -341,7 +341,8 @@ pub fn main() { // This attribute tells resolve to let us call unexported functions let resolve_unexported_str = InternedString::new("!resolve_unexported"); let resolve_unexported_attr = - attr::mk_attr_inner(attr::mk_word_item(resolve_unexported_str)); + attr::mk_attr_inner(attr::mk_attr_id(), + attr::mk_word_item(resolve_unexported_str)); let item = ast::Item { ident: token::str_to_ident("__test"), diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index b3ef888c0b4..77c3d43bc09 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1056,6 +1056,7 @@ fn get_attributes(md: ebml::Doc) -> Vec { attrs.push( codemap::Spanned { node: ast::Attribute_ { + id: attr::mk_attr_id(), style: ast::AttrOuter, value: meta_item, is_sugared_doc: false, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a0742669cc0..a06c6e59ea1 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1436,7 +1436,7 @@ fn synthesize_crate_attrs(ecx: &EncodeContext, fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute { assert!(!ecx.link_meta.crateid.name.is_empty()); - attr::mk_attr_inner( + attr::mk_attr_inner(attr::mk_attr_id(), attr::mk_name_value_item_str( InternedString::new("crate_id"), token::intern_and_get_ident(ecx.link_meta diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 43f3442ec47..4b769a5fdae 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -228,8 +228,9 @@ fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::De let f = decl_rust_fn(ccx, fn_ty, name); csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| { - set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr_outer(x)) - .collect::>().as_slice(), f) + set_llvm_fn_attrs(meta_items.iter().map(|&x| { + attr::mk_attr_outer(attr::mk_attr_id(), x) + }).collect::>().as_slice(), f) }); ccx.externs.borrow_mut().insert(name.to_strbuf(), f); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d4c01746098..e77d1faf05d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1024,9 +1024,13 @@ pub enum AttrStyle { AttrInner, } +#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] +pub struct AttrId(pub uint); + // doc-comments are promoted to attributes that have is_sugared_doc = true #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] pub struct Attribute_ { + pub id: AttrId, pub style: AttrStyle, pub value: @MetaItem, pub is_sugared_doc: bool, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 77c335b8936..83ac2c08efb 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -11,7 +11,7 @@ // Functions dealing with attributes and meta items use ast; -use ast::{Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList}; +use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList}; use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use diagnostic::SpanHandler; @@ -22,6 +22,18 @@ use collections::HashSet; +local_data_key!(used_attrs: HashSet) + +pub fn mark_used(attr: &Attribute) { + let mut used = used_attrs.replace(None).unwrap_or_else(|| HashSet::new()); + used.insert(attr.node.id); + used_attrs.replace(Some(used)); +} + +pub fn is_used(attr: &Attribute) -> bool { + used_attrs.get().map_or(false, |used| used.contains(&attr.node.id)) +} + pub trait AttrMetaMethods { // This could be changed to `fn check_name(&self, name: InternedString) -> // bool` which would facilitate a side table recording which @@ -127,9 +139,9 @@ fn desugar_doc(&self) -> Attribute { token::intern_and_get_ident(strip_doc_comment_decoration( comment.get()).as_slice())); if self.node.style == ast::AttrOuter { - mk_attr_outer(meta) + mk_attr_outer(self.node.id, meta) } else { - mk_attr_inner(meta) + mk_attr_inner(self.node.id, meta) } } else { *self @@ -158,9 +170,18 @@ pub fn mk_word_item(name: InternedString) -> @MetaItem { @dummy_spanned(MetaWord(name)) } +local_data_key!(next_attr_id: uint) + +pub fn mk_attr_id() -> AttrId { + let id = next_attr_id.replace(None).unwrap_or(0); + next_attr_id.replace(Some(id + 1)); + AttrId(id) +} + /// Returns an inner attribute with the given value. -pub fn mk_attr_inner(item: @MetaItem) -> Attribute { +pub fn mk_attr_inner(id: AttrId, item: @MetaItem) -> Attribute { dummy_spanned(Attribute_ { + id: id, style: ast::AttrInner, value: item, is_sugared_doc: false, @@ -168,19 +189,22 @@ pub fn mk_attr_inner(item: @MetaItem) -> Attribute { } /// Returns an outer attribute with the given value. -pub fn mk_attr_outer(item: @MetaItem) -> Attribute { +pub fn mk_attr_outer(id: AttrId, item: @MetaItem) -> Attribute { dummy_spanned(Attribute_ { + id: id, style: ast::AttrOuter, value: item, is_sugared_doc: false, }) } -pub fn mk_sugared_doc_attr(text: InternedString, lo: BytePos, hi: BytePos) +pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos, + hi: BytePos) -> Attribute { let style = doc_comment_style(text.get()); let lit = spanned(lo, hi, ast::LitStr(text, ast::CookedStr)); let attr = Attribute_ { + id: id, style: style, value: @spanned(lo, hi, MetaNameValue(InternedString::new("doc"), lit)), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 3c7415ae0e9..44c177d19ca 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -231,7 +231,7 @@ fn item_ty_poly(&self, generics: Generics) -> @ast::Item; fn item_ty(&self, span: Span, name: Ident, ty: P) -> @ast::Item; - fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute; + fn attribute(&self, id: AttrId, sp: Span, mi: @ast::MetaItem) -> ast::Attribute; fn meta_word(&self, sp: Span, w: InternedString) -> @ast::MetaItem; fn meta_list(&self, @@ -925,8 +925,10 @@ fn item_ty(&self, span: Span, name: Ident, ty: P) -> @ast::Item { self.item_ty_poly(span, name, ty, ast_util::empty_generics()) } - fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute { + fn attribute(&self, id: ast::AttrId, sp: Span, mi: @ast::MetaItem) + -> ast::Attribute { respan(sp, ast::Attribute_ { + id: id, style: ast::AttrOuter, value: mi, is_sugared_doc: false, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 89c94891b33..73bfe9c27b6 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attr; use ast::{MetaItem, Item, Expr}; use codemap::Span; use ext::base::ExtCtxt; @@ -21,7 +22,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 92b3788c247..31d6fcb9d6f 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -9,6 +9,7 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -34,7 +35,7 @@ fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { macro_rules! md ( ($name:expr, $f:ident) => { { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); MethodDef { name: $name, generics: LifetimeBounds::empty(), diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index dd2f90cfa5f..3d79de4feb1 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -10,6 +10,7 @@ use ast; use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -24,7 +25,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, macro_rules! md ( ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); MethodDef { name: $name, generics: LifetimeBounds::empty(), diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index b76caccffec..42bbf8e415a 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -9,6 +9,7 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -37,8 +38,8 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @E let inline = cx.meta_word(span, InternedString::new("inline")); let hidden = cx.meta_word(span, InternedString::new("hidden")); let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); - let attrs = vec!(cx.attribute(span, inline), - cx.attribute(span, doc)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline), + cx.attribute(attr::mk_attr_id(), span, doc)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 3ca4f9e2862..6413bdab344 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -10,6 +10,7 @@ use ast; use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -24,7 +25,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index c225906ed2b..a0499a2cc1e 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -9,6 +9,7 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -21,7 +22,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 0875daddc0f..28595fecd89 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -182,6 +182,7 @@ fn eq(&self, other: &int) -> bool { use ast; use ast::{P, EnumDef, Expr, Ident, Generics, StructDef}; use ast_util; +use attr; use attr::AttrMetaMethods; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -427,6 +428,7 @@ fn create_derived_impl(&self, self_ty_params.into_vec()), None); let attr = cx.attribute( + attr::mk_attr_id(), self.span, cx.meta_word(self.span, InternedString::new("automatically_derived"))); diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 3e6b8d522d4..8b368968f49 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -10,6 +10,7 @@ use ast; use ast::{MetaItem, Item, Expr, MutMutable}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -37,7 +38,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, Path::new(vec!("std", "hash", "sip", "SipState"))) }; let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let hash_trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 5066a395b41..e3621b51c4d 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -10,6 +10,7 @@ use ast::{MetaItem, Item, Expr}; use ast; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -22,7 +23,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 449851dd3ea..c60cdab9099 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -9,6 +9,7 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; +use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -21,7 +22,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 989d0a463c3..83118df5e65 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -972,6 +972,7 @@ mod test { use super::*; use ast; use ast::{Attribute_, AttrOuter, MetaWord}; + use attr; use codemap; use codemap::Spanned; use ext::base::{CrateLoader, MacroCrate}; @@ -1103,6 +1104,7 @@ fn make_dummy_attr(s: &str) -> ast::Attribute { Spanned { span:codemap::DUMMY_SP, node: Attribute_ { + id: attr::mk_attr_id(), style: AttrOuter, value: @Spanned { node: MetaWord(token::intern_and_get_ident(s)), diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index ad4b798cfe5..c3b3c4eed57 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -10,6 +10,7 @@ use ast; use ast::P; +use attr; use codemap::{Span, respan}; use ext::base::*; use ext::base; @@ -382,7 +383,8 @@ fn static_attrs(&self) -> Vec { .meta_word(self.fmtsp, InternedString::new( "address_insignificant")); - let unnamed = self.ecx.attribute(self.fmtsp, unnamed); + let unnamed = self.ecx.attribute(attr::mk_attr_id(), self.fmtsp, + unnamed); // Do not warn format string as dead code let dead_code = self.ecx.meta_word(self.fmtsp, @@ -390,7 +392,8 @@ fn static_attrs(&self) -> Vec { let allow_dead_code = self.ecx.meta_list(self.fmtsp, InternedString::new("allow"), vec!(dead_code)); - let allow_dead_code = self.ecx.attribute(self.fmtsp, allow_dead_code); + let allow_dead_code = self.ecx.attribute(attr::mk_attr_id(), self.fmtsp, + allow_dead_code); return vec!(unnamed, allow_dead_code); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9813e12de01..ae5cf550bb9 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -360,6 +360,7 @@ fn fold_attribute_(at: Attribute, fld: &mut T) -> Attribute { Spanned { span: fld.new_span(at.span), node: ast::Attribute_ { + id: at.node.id, style: at.node.style, value: fold_meta_item_(at.node.value, fld), is_sugared_doc: at.node.is_sugared_doc diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 89d1b8f9342..e86dcb3d311 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attr; use ast; use codemap::{spanned, Spanned, mk_sp, Span}; use parse::common::*; //resolve bug? @@ -39,6 +40,7 @@ fn parse_outer_attributes(&mut self) -> Vec { } token::DOC_COMMENT(s) => { let attr = ::attr::mk_sugared_doc_attr( + attr::mk_attr_id(), self.id_to_interned_str(s), self.span.lo, self.span.hi @@ -101,6 +103,7 @@ fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute { return Spanned { span: span, node: ast::Attribute_ { + id: attr::mk_attr_id(), style: style, value: value, is_sugared_doc: false @@ -132,7 +135,10 @@ fn parse_inner_attrs_and_next(&mut self) // we need to get the position of this token before we bump. let Span { lo, hi, .. } = self.span; self.bump(); - ::attr::mk_sugared_doc_attr(self.id_to_interned_str(s), lo, hi) + ::attr::mk_sugared_doc_attr(attr::mk_attr_id(), + self.id_to_interned_str(s), + lo, + hi) } _ => { break; From 50181add04279eaac2b078d36823035933844226 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 20 May 2014 22:07:42 -0700 Subject: [PATCH 2/6] First sketch of lint pass Enough attributes are marked to cleanly compile an empty library. --- src/librustc/front/feature_gate.rs | 2 +- src/librustc/front/std_inject.rs | 6 ++++++ src/librustc/middle/lint.rs | 21 ++++++++++++++++++++- src/libsyntax/attr.rs | 14 +++++++++++--- src/libsyntax/ext/expand.rs | 2 +- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 21a7fc8d150..4f9957ee980 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -327,7 +327,7 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) { }; for attr in krate.attrs.iter() { - if !attr.name().equiv(&("feature")) { + if !attr.check_name("feature") { continue } diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index e380af7a4f0..fe636f7b686 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -115,6 +115,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { InternedString::new("feature"), vec![attr::mk_word_item(InternedString::new("phase"))], )); + // std_inject runs after feature checking so manually mark this attr + attr::mark_used(&feat_phase_attr); krate.attrs.push(feat_phase_attr); krate @@ -141,6 +143,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { let no_std_attr = attr::mk_attr_inner(attr::mk_attr_id(), attr::mk_word_item(InternedString::new("no_std"))); + // std_inject runs after feature checking so manually mark this attr + attr::mark_used(&no_std_attr); krate.attrs.push(no_std_attr); if !no_prelude(krate.attrs.as_slice()) { @@ -154,6 +158,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { vec!( attr::mk_word_item(InternedString::new("globs")), ))); + // std_inject runs after feature checking so manually mark this attr + attr::mark_used(&globs_attr); krate.attrs.push(globs_attr); krate.module = self.fold_mod(&krate.module); diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 8feacba6e00..6b5b98376b6 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -90,6 +90,7 @@ pub enum Lint { UnusedUnsafe, UnsafeBlock, AttributeUsage, + UnusedAttribute, UnknownFeatures, UnknownCrateType, UnsignedNegate, @@ -288,6 +289,13 @@ enum LintSource { default: Warn }), + ("unused_attribute", + LintSpec { + lint: UnusedAttribute, + desc: "detects attributes that were not used by the compiler", + default: Allow + }), + ("unused_variable", LintSpec { lint: UnusedVariable, @@ -619,7 +627,7 @@ pub fn each_lint(sess: &session::Session, let xs = [Allow, Warn, Deny, Forbid]; for &level in xs.iter() { let level_name = level_to_str(level); - for attr in attrs.iter().filter(|m| m.name().equiv(&level_name)) { + for attr in attrs.iter().filter(|m| m.check_name(level_name)) { let meta = attr.node.value; let metas = match meta.node { ast::MetaList(_, ref metas) => metas, @@ -1137,6 +1145,15 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { } } +fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { + for attr in attrs.iter() { + if !attr::is_used(attr) { + cx.span_lint(UnusedAttribute, attr.span, + format!("unused attribute {}", attr.name()).as_slice()); + } + } +} + fn check_heap_expr(cx: &Context, e: &ast::Expr) { let ty = ty::expr_ty(cx.tcx, e); check_heap_type(cx, e.span, ty); @@ -1694,6 +1711,7 @@ fn visit_item(&mut self, it: &ast::Item, _: ()) { check_heap_item(cx, it); check_missing_doc_item(cx, it); check_attrs_usage(cx, it.attrs.as_slice()); + check_unused_attribute(cx, it.attrs.as_slice()); check_raw_ptr_deriving(cx, it); cx.visit_ids(|v| v.visit_item(it, ())); @@ -1900,6 +1918,7 @@ pub fn check_crate(tcx: &ty::ctxt, check_crate_attrs_usage(cx, krate.attrs.as_slice()); // since the root module isn't visited as an item (because it isn't an item), warn for it // here. + check_unused_attribute(cx, krate.attrs.as_slice()); check_missing_doc_attrs(cx, None, krate.attrs.as_slice(), diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 83ac2c08efb..ac5792febbb 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -35,9 +35,9 @@ pub fn is_used(attr: &Attribute) -> bool { } pub trait AttrMetaMethods { - // This could be changed to `fn check_name(&self, name: InternedString) -> - // bool` which would facilitate a side table recording which - // attributes/meta items are used/unused. + fn check_name(&self, name: &str) -> bool { + name == self.name().get() + } /// Retrieve the name of the meta item, e.g. foo in #[foo], /// #[foo="bar"] and #[foo(bar)] @@ -59,6 +59,14 @@ pub trait AttrMetaMethods { } impl AttrMetaMethods for Attribute { + fn check_name(&self, name: &str) -> bool { + if name == self.name().get() { + mark_used(self); + true + } else { + false + } + } fn name(&self) -> InternedString { self.meta().name() } fn value_str(&self) -> Option { self.meta().value_str() diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 83118df5e65..64b7e1c28c1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -474,7 +474,7 @@ pub fn expand_view_item(vi: &ast::ViewItem, match vi.node { ast::ViewItemExternCrate(..) => { let should_load = vi.attrs.iter().any(|attr| { - attr.name().get() == "phase" && + attr.check_name("phase") && attr.meta_item_list().map_or(false, |phases| { attr::contains_name(phases, "syntax") }) From e0648093d8f8cc4db3b309622b7efd95275a17d3 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 21 May 2014 00:05:45 -0700 Subject: [PATCH 3/6] Port more stuff to mark used attributes --- src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 10 +---- src/librustc/middle/lint.rs | 13 +++---- src/librustc/middle/trans/base.rs | 6 +-- src/librustc/middle/ty.rs | 14 ++++--- src/librustdoc/html/render.rs | 4 +- src/libsyntax/attr.rs | 64 +++++++++++++++++++------------ src/libsyntax/ext/expand.rs | 3 ++ 8 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index f30e24a3151..d2b567395f0 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -176,7 +176,7 @@ pub fn get_static_methods_if_impl(cstore: &cstore::CStore, pub fn get_item_attrs(cstore: &cstore::CStore, def_id: ast::DefId, - f: |Vec<@ast::MetaItem> |) { + f: |Vec |) { let cdata = cstore.get_crate_data(def_id.krate); decoder::get_item_attrs(&*cdata, def_id.node, f) } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 77c3d43bc09..54243ea6f1f 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -953,20 +953,14 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, pub fn get_item_attrs(cdata: Cmd, orig_node_id: ast::NodeId, - f: |Vec<@ast::MetaItem> |) { + f: |Vec|) { // The attributes for a tuple struct are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id); let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id); let item = lookup_item(node_id, cdata.data()); - reader::tagged_docs(item, tag_attributes, |attributes| { - reader::tagged_docs(attributes, tag_attribute, |attribute| { - f(get_meta_items(attribute)); - true - }); - true - }); + f(get_attributes(item)); } fn struct_field_family_to_visibility(family: Family) -> ast::Visibility { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 6b5b98376b6..5f7376396e4 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -64,7 +64,7 @@ use syntax::abi; use syntax::ast_map; use syntax::ast_util::IdVisitingOperation; -use syntax::attr::{AttrMetaMethods, AttributeMethods}; +use syntax::attr::AttrMetaMethods; use syntax::attr; use syntax::codemap::Span; use syntax::parse::token::InternedString; @@ -1148,8 +1148,7 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { for attr in attrs.iter() { if !attr::is_used(attr) { - cx.span_lint(UnusedAttribute, attr.span, - format!("unused attribute {}", attr.name()).as_slice()); + cx.span_lint(UnusedAttribute, attr.span, "unused attribute"); } } } @@ -1654,9 +1653,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) { let stability = if ast_util::is_local(id) { // this crate let s = cx.tcx.map.with_attrs(id.node, |attrs| { - attrs.map(|a| { - attr::find_stability(a.iter().map(|a| a.meta())) - }) + attrs.map(|a| attr::find_stability(a.as_slice())) }); match s { Some(s) => s, @@ -1672,9 +1669,9 @@ fn check_stability(cx: &Context, e: &ast::Expr) { let mut s = None; // run through all the attributes and take the first // stability one. - csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |meta_items| { + csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |attrs| { if s.is_none() { - s = attr::find_stability(meta_items.move_iter()) + s = attr::find_stability(attrs.as_slice()) } }); s diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 4b769a5fdae..da28c3008dd 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -227,10 +227,8 @@ fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::De let f = decl_rust_fn(ccx, fn_ty, name); - csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| { - set_llvm_fn_attrs(meta_items.iter().map(|&x| { - attr::mk_attr_outer(attr::mk_attr_id(), x) - }).collect::>().as_slice(), f) + csearch::get_item_attrs(&ccx.sess().cstore, did, |attrs| { + set_llvm_fn_attrs(attrs.as_slice(), f) }); ccx.externs.borrow_mut().insert(name.to_strbuf(), f); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 64619b636a3..9176b33331f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3889,20 +3889,22 @@ pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc { } } -/// Iterate over meta_items of a definition. +/// Iterate over attributes of a definition. // (This should really be an iterator, but that would require csearch and // decoder to use iterators instead of higher-order functions.) -pub fn each_attr(tcx: &ctxt, did: DefId, f: |@ast::MetaItem| -> bool) -> bool { +pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool { if is_local(did) { let item = tcx.map.expect_item(did.node); - item.attrs.iter().advance(|attr| f(attr.node.value)) + item.attrs.iter().advance(|attr| f(attr)) } else { + info!("getting foreign attrs"); let mut cont = true; - csearch::get_item_attrs(&tcx.sess.cstore, did, |meta_items| { + csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| { if cont { - cont = meta_items.iter().advance(|ptrptr| f(*ptrptr)); + cont = attrs.iter().advance(|attr| f(attr)); } }); + info!("done"); cont } } @@ -3911,7 +3913,7 @@ pub fn each_attr(tcx: &ctxt, did: DefId, f: |@ast::MetaItem| -> bool) -> bool { pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool { let mut found = false; each_attr(tcx, did, |item| { - if item.name().equiv(&attr) { + if item.check_name(attr) { found = true; false } else { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8744553955a..b09ac8f94af 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1091,8 +1091,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { shortty(self.item), self.item.name.get_ref().as_slice())); // Write stability attributes - match attr::find_stability(self.item.attrs.iter()) { - Some(ref stability) => { + match attr::find_stability_generic(self.item.attrs.iter()) { + Some((ref stability, _)) => { try!(write!(fmt, "{lvl}", lvl = stability.level.to_str(), diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index ac5792febbb..bbd333163b5 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -238,14 +238,14 @@ pub fn contains_name(metas: &[AM], name: &str) -> bool { debug!("attr::contains_name (name={})", name); metas.iter().any(|item| { debug!(" testing: {}", item.name()); - item.name().equiv(&name) + item.check_name(name) }) } pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option { attrs.iter() - .find(|at| at.name().equiv(&name)) + .find(|at| at.check_name(name)) .and_then(|at| at.value_str()) } @@ -253,7 +253,7 @@ pub fn last_meta_item_value_str_by_name(items: &[@MetaItem], name: &str) -> Option { items.iter() .rev() - .find(|mi| mi.name().equiv(&name)) + .find(|mi| mi.check_name(name)) .and_then(|i| i.value_str()) } @@ -289,7 +289,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> Vec<@MetaItem> { */ pub fn find_linkage_metas(attrs: &[Attribute]) -> Vec<@MetaItem> { let mut result = Vec::new(); - for attr in attrs.iter().filter(|at| at.name().equiv(&("link"))) { + for attr in attrs.iter().filter(|at| at.check_name("link")) { match attr.meta().node { MetaList(_, ref items) => result.push_all(items.as_slice()), _ => () @@ -318,17 +318,21 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] attrs.iter().fold(InlineNone, |ia,attr| { match attr.node.value.node { - MetaWord(ref n) if n.equiv(&("inline")) => InlineHint, - MetaList(ref n, ref items) if n.equiv(&("inline")) => { - if contains_name(items.as_slice(), "always") { - InlineAlways - } else if contains_name(items.as_slice(), "never") { - InlineNever - } else { + MetaWord(ref n) if n.equiv(&("inline")) => { + mark_used(attr); InlineHint } - } - _ => ia + MetaList(ref n, ref items) if n.equiv(&("inline")) => { + mark_used(attr); + if contains_name(items.as_slice(), "always") { + InlineAlways + } else if contains_name(items.as_slice(), "never") { + InlineNever + } else { + InlineHint + } + } + _ => ia } }) } @@ -348,7 +352,7 @@ pub fn test_cfg> // this doesn't work. let some_cfg_matches = metas.any(|mi| { debug!("testing name: {}", mi.name()); - if mi.name().equiv(&("cfg")) { // it is a #[cfg()] attribute + if mi.check_name("cfg") { // it is a #[cfg()] attribute debug!("is cfg"); no_cfgs = false; // only #[cfg(...)] ones are understood. @@ -399,11 +403,13 @@ pub enum StabilityLevel { Locked } -/// Find the first stability attribute. `None` if none exists. -pub fn find_stability>(mut metas: It) - -> Option { - for m in metas { - let level = match m.name().get() { +pub fn find_stability_generic<'a, + AM: AttrMetaMethods, + I: Iterator<&'a AM>> + (mut attrs: I) + -> Option<(Stability, &'a AM)> { + for attr in attrs { + let level = match attr.name().get() { "deprecated" => Deprecated, "experimental" => Experimental, "unstable" => Unstable, @@ -413,14 +419,22 @@ pub fn find_stability>(mut metas: It) _ => continue // not a stability level }; - return Some(Stability { + return Some((Stability { level: level, - text: m.value_str() - }); + text: attr.value_str() + }, attr)); } None } +/// Find the first stability attribute. `None` if none exists. +pub fn find_stability(attrs: &[Attribute]) -> Option { + find_stability_generic(attrs.iter()).map(|(s, attr)| { + mark_used(attr); + s + }) +} + pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) { let mut set = HashSet::new(); for meta in metas.iter() { @@ -447,11 +461,13 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) { * present (before fields, if any) with that type; reprensentation * optimizations which would remove it will not be done. */ -pub fn find_repr_attr(diagnostic: &SpanHandler, attr: @ast::MetaItem, acc: ReprAttr) +pub fn find_repr_attr(diagnostic: &SpanHandler, attr: &Attribute, acc: ReprAttr) -> ReprAttr { let mut acc = acc; - match attr.node { + info!("{}", ::print::pprust::attribute_to_str(attr)); + match attr.node.value.node { ast::MetaList(ref s, ref items) if s.equiv(&("repr")) => { + mark_used(attr); for item in items.iter() { match item.node { ast::MetaWord(ref word) => { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 64b7e1c28c1..658e4bafbe2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -265,6 +265,8 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) match fld.extsbox.find(&intern(mname.get())) { Some(&ItemDecorator(dec_fn)) => { + attr::mark_used(attr); + fld.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { @@ -336,6 +338,7 @@ fn expand_item_modifiers(mut it: @ast::Item, fld: &mut MacroExpander) match fld.extsbox.find(&intern(mname.get())) { Some(&ItemModifier(dec_fn)) => { + attr::mark_used(attr); fld.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { From 24f98c6d7a1dcf878e13f506d9b164fa54657503 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 21 May 2014 19:02:40 -0700 Subject: [PATCH 4/6] Whitelist doc attributes This is a bit overly permissive but should be okay for now. --- src/librustc/middle/lint.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 5f7376396e4..5315b223344 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -1147,6 +1147,9 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { for attr in attrs.iter() { + // whitelist docs since rustdoc looks at them + attr.check_name("doc"); + if !attr::is_used(attr) { cx.span_lint(UnusedAttribute, attr.span, "unused attribute"); } From 864c5016ae5492da8130bf3c1c2d5ef04b66efa7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 22 May 2014 22:29:13 -0700 Subject: [PATCH 5/6] Get "make check" to work with unused-attribute There's a fair number of attributes that have to be whitelisted since they're either looked for by rustdoc, in trans, or as needed. These can be cleaned up in the future. --- src/doc/rust.md | 1 + src/doc/rustdoc.md | 1 + src/doc/tutorial.md | 5 ++ src/librustc/driver/driver.rs | 78 ++++++++++---------- src/librustc/front/test.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/lint.rs | 32 +++++++- src/librustdoc/clean.rs | 6 +- src/libsyntax/attr.rs | 7 +- src/test/compile-fail/lint-misplaced-attr.rs | 3 + src/test/compile-fail/lint-obsolete-attr.rs | 3 + src/test/compile-fail/lint-unknown-attr.rs | 4 + src/test/run-pass/attr-mix-new.rs | 1 + src/test/run-pass/backtrace.rs | 2 - src/test/run-pass/class-attributes-1.rs | 1 + src/test/run-pass/class-attributes-2.rs | 1 + src/test/run-pass/issue-3250.rs | 15 ---- src/test/run-pass/item-attributes.rs | 1 + src/test/run-pass/method-attributes.rs | 1 + 19 files changed, 102 insertions(+), 64 deletions(-) delete mode 100644 src/test/run-pass/issue-3250.rs diff --git a/src/doc/rust.md b/src/doc/rust.md index d686a02b2fe..b8fa4075e7a 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -661,6 +661,7 @@ Attributes on the anonymous crate module define important metadata that influenc the behavior of the compiler. ~~~~ {.rust} +# #![allow(unused_attribute)] // Crate ID #![crate_id = "projx#2.5"] diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index d6cb782bd83..af9cff7be67 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -11,6 +11,7 @@ Documenting Rust APIs is quite simple. To document a given item, we have "doc comments": ~~~ +# #![allow(unused_attribute)] // the "link" crate attribute is currently required for rustdoc, but normally // isn't needed. #![crate_id = "universe"] diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index da78869d9fa..d85734508bc 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -3166,6 +3166,7 @@ without conflict. Therefore, if you plan to compile your crate as a library, you should annotate it with that information: ~~~~ +# #![allow(unused_attribute)] // `lib.rs` # #![crate_type = "lib"] @@ -3189,6 +3190,7 @@ Other crate settings and metadata include things like enabling/disabling certain or setting the crate type (library or executable) explicitly: ~~~~ +# #![allow(unused_attribute)] // `lib.rs` // ... @@ -3208,6 +3210,7 @@ Now for something that you can actually compile yourself. We define two crates, and use one of them as a library in the other. ~~~~ +# #![allow(unused_attribute)] // `world.rs` #![crate_id = "world#0.42"] @@ -3282,11 +3285,13 @@ fn main() { Both auto-insertions can be disabled with an attribute if necessary: ~~~ +# #![allow(unused_attribute)] // In the crate root: #![no_std] ~~~ ~~~ +# #![allow(unused_attribute)] // In any module: #![no_implicit_prelude] ~~~ diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4e682e8e34b..ee9b10a8059 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -716,6 +716,45 @@ fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> { pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { + // Unconditionally collect crate types from attributes to make them used + let attr_types: Vec = attrs.iter().filter_map(|a| { + if a.check_name("crate_type") { + match a.value_str() { + Some(ref n) if n.equiv(&("rlib")) => { + Some(config::CrateTypeRlib) + } + Some(ref n) if n.equiv(&("dylib")) => { + Some(config::CrateTypeDylib) + } + Some(ref n) if n.equiv(&("lib")) => { + Some(config::default_lib_output()) + } + Some(ref n) if n.equiv(&("staticlib")) => { + Some(config::CrateTypeStaticlib) + } + Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable), + Some(_) => { + session.add_lint(lint::UnknownCrateType, + ast::CRATE_NODE_ID, + a.span, + "invalid `crate_type` \ + value".to_strbuf()); + None + } + _ => { + session.add_lint(lint::UnknownCrateType, + ast::CRATE_NODE_ID, + a.span, + "`crate_type` requires a \ + value".to_strbuf()); + None + } + } + } else { + None + } + }).collect(); + // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { @@ -729,44 +768,7 @@ pub fn collect_crate_types(session: &Session, if base.len() > 0 { return base } else { - let iter = attrs.iter().filter_map(|a| { - if a.name().equiv(&("crate_type")) { - match a.value_str() { - Some(ref n) if n.equiv(&("rlib")) => { - Some(config::CrateTypeRlib) - } - Some(ref n) if n.equiv(&("dylib")) => { - Some(config::CrateTypeDylib) - } - Some(ref n) if n.equiv(&("lib")) => { - Some(config::default_lib_output()) - } - Some(ref n) if n.equiv(&("staticlib")) => { - Some(config::CrateTypeStaticlib) - } - Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable), - Some(_) => { - session.add_lint(lint::UnknownCrateType, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` \ - value".to_strbuf()); - None - } - _ => { - session.add_lint(lint::UnknownCrateType, - ast::CRATE_NODE_ID, - a.span, - "`crate_type` requires a \ - value".to_strbuf()); - None - } - } - } else { - None - } - }); - base.extend(iter); + base.extend(attr_types.move_iter()); if base.len() == 0 { base.push(config::CrateTypeExecutable); } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index d5e9192cd74..67944423808 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -253,7 +253,7 @@ fn has_test_signature(i: @ast::Item) -> bool { fn is_ignored(cx: &TestCtxt, i: @ast::Item) -> bool { i.attrs.iter().any(|attr| { // check ignore(cfg(foo, bar)) - attr.name().equiv(&("ignore")) && match attr.meta_item_list() { + attr.check_name("ignore") && match attr.meta_item_list() { Some(ref cfgs) => { attr::test_cfg(cx.config.as_slice(), cfgs.iter().map(|x| *x)) } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a06c6e59ea1..2e3dc360ac2 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1447,7 +1447,7 @@ fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute { let mut attrs = Vec::new(); for attr in krate.attrs.iter() { - if !attr.name().equiv(&("crate_id")) { + if !attr.check_name("crate_id") { attrs.push(*attr); } } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 5315b223344..25a0f151090 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -293,7 +293,7 @@ enum LintSource { LintSpec { lint: UnusedAttribute, desc: "detects attributes that were not used by the compiler", - default: Allow + default: Warn }), ("unused_variable", @@ -1148,8 +1148,38 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { for attr in attrs.iter() { // whitelist docs since rustdoc looks at them + attr.check_name("automatically_derived"); attr.check_name("doc"); + // these are processed in trans, which happens after the lint pass + attr.check_name("address_insignificant"); + attr.check_name("cold"); + attr.check_name("inline"); + attr.check_name("link"); + attr.check_name("link_name"); + attr.check_name("link_section"); + attr.check_name("no_builtins"); + attr.check_name("no_mangle"); + attr.check_name("no_split_stack"); + attr.check_name("packed"); + attr.check_name("static_assert"); + attr.check_name("thread_local"); + + // not used anywhere (!?) but apparently we want to keep them around + attr.check_name("comment"); + attr.check_name("desc"); + attr.check_name("license"); + + // these are only looked at on-demand so we can't guarantee they'll have + // already been checked + attr.check_name("deprecated"); + attr.check_name("experimental"); + attr.check_name("frozen"); + attr.check_name("locked"); + attr.check_name("must_use"); + attr.check_name("stable"); + attr.check_name("unstable"); + if !attr::is_used(attr) { cx.span_lint(UnusedAttribute, attr.span, "unused attribute"); } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index fb2a80333e8..6f3c6e4cd6f 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -314,9 +314,9 @@ fn clean(&self) -> Attribute { } // This is a rough approximation that gets us what we want. -impl<'a> attr::AttrMetaMethods for &'a Attribute { +impl attr::AttrMetaMethods for Attribute { fn name(&self) -> InternedString { - match **self { + match *self { Word(ref n) | List(ref n, _) | NameValue(ref n, _) => { token::intern_and_get_ident(n.as_slice()) } @@ -324,7 +324,7 @@ fn name(&self) -> InternedString { } fn value_str(&self) -> Option { - match **self { + match *self { NameValue(_, ref v) => { Some(token::intern_and_get_ident(v.as_slice())) } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index bbd333163b5..1d43ac898f1 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -350,9 +350,9 @@ pub fn test_cfg> // this would be much nicer as a chain of iterator adaptors, but // this doesn't work. - let some_cfg_matches = metas.any(|mi| { + let some_cfg_matches = metas.fold(false, |matches, mi| { debug!("testing name: {}", mi.name()); - if mi.check_name("cfg") { // it is a #[cfg()] attribute + let this_matches = if mi.check_name("cfg") { // it is a #[cfg()] attribute debug!("is cfg"); no_cfgs = false; // only #[cfg(...)] ones are understood. @@ -380,7 +380,8 @@ pub fn test_cfg> } } else { false - } + }; + matches || this_matches }); debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", no_cfgs, some_cfg_matches); no_cfgs || some_cfg_matches diff --git a/src/test/compile-fail/lint-misplaced-attr.rs b/src/test/compile-fail/lint-misplaced-attr.rs index d422dfc513d..f7db5c97aab 100644 --- a/src/test/compile-fail/lint-misplaced-attr.rs +++ b/src/test/compile-fail/lint-misplaced-attr.rs @@ -12,9 +12,12 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] mod a { #![crate_type = "bin"] //~ ERROR: crate-level attribute + //~^ ERROR: unused attribute } #[crate_type = "bin"] fn main() {} //~ ERROR: crate-level attribute + //~^ ERROR: unused attribute diff --git a/src/test/compile-fail/lint-obsolete-attr.rs b/src/test/compile-fail/lint-obsolete-attr.rs index 8b70953146d..32058737ed3 100644 --- a/src/test/compile-fail/lint-obsolete-attr.rs +++ b/src/test/compile-fail/lint-obsolete-attr.rs @@ -12,10 +12,13 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] #![allow(dead_code)] #[abi="stdcall"] extern {} //~ ERROR: obsolete attribute + //~^ ERROR: unused attribute #[fixed_stack_segment] fn f() {} //~ ERROR: obsolete attribute + //~^ ERROR: unused attribute fn main() {} diff --git a/src/test/compile-fail/lint-unknown-attr.rs b/src/test/compile-fail/lint-unknown-attr.rs index dbbf91f725d..32c0722d1ac 100644 --- a/src/test/compile-fail/lint-unknown-attr.rs +++ b/src/test/compile-fail/lint-unknown-attr.rs @@ -12,9 +12,13 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] #![mutable_doc] //~ ERROR: unknown crate attribute + //~^ ERROR: unused attribute #[dance] mod a {} //~ ERROR: unknown attribute + //~^ ERROR: unused attribute #[dance] fn main() {} //~ ERROR: unknown attribute + //~^ ERROR: unused attribute diff --git a/src/test/run-pass/attr-mix-new.rs b/src/test/run-pass/attr-mix-new.rs index af615912f28..55ca75b4b71 100644 --- a/src/test/run-pass/attr-mix-new.rs +++ b/src/test/run-pass/attr-mix-new.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attribute)] #[foo(bar)] mod foo { diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 7f2c9e14af1..cf6126a37fa 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-win32 FIXME #13259 -#![no_uv] - extern crate native; use std::os; diff --git a/src/test/run-pass/class-attributes-1.rs b/src/test/run-pass/class-attributes-1.rs index 55cf41d73d5..186fec45c4b 100644 --- a/src/test/run-pass/class-attributes-1.rs +++ b/src/test/run-pass/class-attributes-1.rs @@ -9,6 +9,7 @@ // except according to those terms. // pp-exact - Make sure we actually print the attributes +#![allow(unused_attribute)] struct cat { name: StrBuf, diff --git a/src/test/run-pass/class-attributes-2.rs b/src/test/run-pass/class-attributes-2.rs index b1ed70278ef..6da8123c8c4 100644 --- a/src/test/run-pass/class-attributes-2.rs +++ b/src/test/run-pass/class-attributes-2.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attribute)] struct cat { name: StrBuf, diff --git a/src/test/run-pass/issue-3250.rs b/src/test/run-pass/issue-3250.rs deleted file mode 100644 index 255f6b1635c..00000000000 --- a/src/test/run-pass/issue-3250.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[auto_serialize] - -type t = (uint, uint); - -pub fn main() { } diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index ef825826ea4..bf94af601fe 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -11,6 +11,7 @@ // These are attributes of the implicit crate. Really this just needs to parse // for completeness since .rs files linked from .rc files support this // notation to specify their module's attributes +#![allow(unused_attribute)] #![attr1 = "val"] #![attr2 = "val"] #![attr3] diff --git a/src/test/run-pass/method-attributes.rs b/src/test/run-pass/method-attributes.rs index 87c43da9ebc..c015244d520 100644 --- a/src/test/run-pass/method-attributes.rs +++ b/src/test/run-pass/method-attributes.rs @@ -9,6 +9,7 @@ // except according to those terms. // pp-exact - Make sure we print all the attributes +#![allow(unused_attribute)] #[frobable] trait frobable { From 334799326486e46b67c5405ba9584a26878988a4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 23 May 2014 08:39:26 -0700 Subject: [PATCH 6/6] Changes from feedback --- src/librustc/middle/lint.rs | 65 ++++++++++++---------- src/libsyntax/attr.rs | 19 ++++--- src/libsyntax/ext/build.rs | 8 +-- src/libsyntax/ext/deriving/clone.rs | 3 +- src/libsyntax/ext/deriving/cmp/eq.rs | 3 +- src/libsyntax/ext/deriving/cmp/ord.rs | 3 +- src/libsyntax/ext/deriving/cmp/totaleq.rs | 5 +- src/libsyntax/ext/deriving/cmp/totalord.rs | 3 +- src/libsyntax/ext/deriving/default.rs | 3 +- src/libsyntax/ext/deriving/generic/mod.rs | 3 +- src/libsyntax/ext/deriving/hash.rs | 3 +- src/libsyntax/ext/deriving/primitive.rs | 3 +- src/libsyntax/ext/deriving/zero.rs | 3 +- src/libsyntax/ext/format.rs | 7 +-- src/libsyntax/parse/attr.rs | 8 +-- 15 files changed, 68 insertions(+), 71 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 25a0f151090..2b1e28548f9 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -1146,39 +1146,46 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { } fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { - for attr in attrs.iter() { - // whitelist docs since rustdoc looks at them - attr.check_name("automatically_derived"); - attr.check_name("doc"); + static ATTRIBUTE_WHITELIST: &'static [&'static str] = &'static [ + // FIXME: #14408 whitelist docs since rustdoc looks at them + "doc", - // these are processed in trans, which happens after the lint pass - attr.check_name("address_insignificant"); - attr.check_name("cold"); - attr.check_name("inline"); - attr.check_name("link"); - attr.check_name("link_name"); - attr.check_name("link_section"); - attr.check_name("no_builtins"); - attr.check_name("no_mangle"); - attr.check_name("no_split_stack"); - attr.check_name("packed"); - attr.check_name("static_assert"); - attr.check_name("thread_local"); + // FIXME: #14406 these are processed in trans, which happens after the + // lint pass + "address_insignificant", + "cold", + "inline", + "link", + "link_name", + "link_section", + "no_builtins", + "no_mangle", + "no_split_stack", + "packed", + "static_assert", + "thread_local", // not used anywhere (!?) but apparently we want to keep them around - attr.check_name("comment"); - attr.check_name("desc"); - attr.check_name("license"); + "comment", + "desc", + "license", - // these are only looked at on-demand so we can't guarantee they'll have - // already been checked - attr.check_name("deprecated"); - attr.check_name("experimental"); - attr.check_name("frozen"); - attr.check_name("locked"); - attr.check_name("must_use"); - attr.check_name("stable"); - attr.check_name("unstable"); + // FIXME: #14407 these are only looked at on-demand so we can't + // guarantee they'll have already been checked + "deprecated", + "experimental", + "frozen", + "locked", + "must_use", + "stable", + "unstable", + ]; + for attr in attrs.iter() { + for &name in ATTRIBUTE_WHITELIST.iter() { + if attr.check_name(name) { + break; + } + } if !attr::is_used(attr) { cx.span_lint(UnusedAttribute, attr.span, "unused attribute"); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 1d43ac898f1..527e851ae35 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -21,17 +21,20 @@ use crateid::CrateId; use collections::HashSet; +use collections::bitv::BitvSet; -local_data_key!(used_attrs: HashSet) +local_data_key!(used_attrs: BitvSet) pub fn mark_used(attr: &Attribute) { - let mut used = used_attrs.replace(None).unwrap_or_else(|| HashSet::new()); - used.insert(attr.node.id); + let mut used = used_attrs.replace(None).unwrap_or_else(|| BitvSet::new()); + let AttrId(id) = attr.node.id; + used.insert(id); used_attrs.replace(Some(used)); } pub fn is_used(attr: &Attribute) -> bool { - used_attrs.get().map_or(false, |used| used.contains(&attr.node.id)) + let AttrId(id) = attr.node.id; + used_attrs.get().map_or(false, |used| used.contains(&id)) } pub trait AttrMetaMethods { @@ -60,12 +63,11 @@ fn check_name(&self, name: &str) -> bool { impl AttrMetaMethods for Attribute { fn check_name(&self, name: &str) -> bool { - if name == self.name().get() { + let matches = name == self.name().get(); + if matches { mark_used(self); - true - } else { - false } + matches } fn name(&self) -> InternedString { self.meta().name() } fn value_str(&self) -> Option { @@ -465,7 +467,6 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) { pub fn find_repr_attr(diagnostic: &SpanHandler, attr: &Attribute, acc: ReprAttr) -> ReprAttr { let mut acc = acc; - info!("{}", ::print::pprust::attribute_to_str(attr)); match attr.node.value.node { ast::MetaList(ref s, ref items) if s.equiv(&("repr")) => { mark_used(attr); diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 44c177d19ca..449feb3afbf 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -12,6 +12,7 @@ use ast::{P, Ident}; use ast; use ast_util; +use attr; use codemap::{Span, respan, Spanned, DUMMY_SP}; use ext::base::ExtCtxt; use ext::quote::rt::*; @@ -231,7 +232,7 @@ fn item_ty_poly(&self, generics: Generics) -> @ast::Item; fn item_ty(&self, span: Span, name: Ident, ty: P) -> @ast::Item; - fn attribute(&self, id: AttrId, sp: Span, mi: @ast::MetaItem) -> ast::Attribute; + fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute; fn meta_word(&self, sp: Span, w: InternedString) -> @ast::MetaItem; fn meta_list(&self, @@ -925,10 +926,9 @@ fn item_ty(&self, span: Span, name: Ident, ty: P) -> @ast::Item { self.item_ty_poly(span, name, ty, ast_util::empty_generics()) } - fn attribute(&self, id: ast::AttrId, sp: Span, mi: @ast::MetaItem) - -> ast::Attribute { + fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute { respan(sp, ast::Attribute_ { - id: id, + id: attr::mk_attr_id(), style: ast::AttrOuter, value: mi, is_sugared_doc: false, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 73bfe9c27b6..89c94891b33 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use attr; use ast::{MetaItem, Item, Expr}; use codemap::Span; use ext::base::ExtCtxt; @@ -22,7 +21,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 31d6fcb9d6f..92b3788c247 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -9,7 +9,6 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -35,7 +34,7 @@ fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { macro_rules! md ( ($name:expr, $f:ident) => { { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); MethodDef { name: $name, generics: LifetimeBounds::empty(), diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 3d79de4feb1..dd2f90cfa5f 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -10,7 +10,6 @@ use ast; use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -25,7 +24,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, macro_rules! md ( ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); MethodDef { name: $name, generics: LifetimeBounds::empty(), diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 42bbf8e415a..b76caccffec 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -9,7 +9,6 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -38,8 +37,8 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @E let inline = cx.meta_word(span, InternedString::new("inline")); let hidden = cx.meta_word(span, InternedString::new("hidden")); let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline), - cx.attribute(attr::mk_attr_id(), span, doc)); + let attrs = vec!(cx.attribute(span, inline), + cx.attribute(span, doc)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 6413bdab344..3ca4f9e2862 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -10,7 +10,6 @@ use ast; use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -25,7 +24,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index a0499a2cc1e..c225906ed2b 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -9,7 +9,6 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -22,7 +21,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 28595fecd89..5f18193437e 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -428,10 +428,11 @@ fn create_derived_impl(&self, self_ty_params.into_vec()), None); let attr = cx.attribute( - attr::mk_attr_id(), self.span, cx.meta_word(self.span, InternedString::new("automatically_derived"))); + // Just mark it now since we know that it'll end up used downstream + attr::mark_used(&attr); let opt_trait_ref = Some(trait_ref); let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type); cx.item( diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 8b368968f49..3e6b8d522d4 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -10,7 +10,6 @@ use ast; use ast::{MetaItem, Item, Expr, MutMutable}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -38,7 +37,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, Path::new(vec!("std", "hash", "sip", "SipState"))) }; let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let hash_trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index e3621b51c4d..5066a395b41 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -10,7 +10,6 @@ use ast::{MetaItem, Item, Expr}; use ast; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -23,7 +22,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index c60cdab9099..449851dd3ea 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -9,7 +9,6 @@ // except according to those terms. use ast::{MetaItem, Item, Expr}; -use attr; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -22,7 +21,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(attr::mk_attr_id(), span, inline)); + let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index c3b3c4eed57..ad4b798cfe5 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -10,7 +10,6 @@ use ast; use ast::P; -use attr; use codemap::{Span, respan}; use ext::base::*; use ext::base; @@ -383,8 +382,7 @@ fn static_attrs(&self) -> Vec { .meta_word(self.fmtsp, InternedString::new( "address_insignificant")); - let unnamed = self.ecx.attribute(attr::mk_attr_id(), self.fmtsp, - unnamed); + let unnamed = self.ecx.attribute(self.fmtsp, unnamed); // Do not warn format string as dead code let dead_code = self.ecx.meta_word(self.fmtsp, @@ -392,8 +390,7 @@ fn static_attrs(&self) -> Vec { let allow_dead_code = self.ecx.meta_list(self.fmtsp, InternedString::new("allow"), vec!(dead_code)); - let allow_dead_code = self.ecx.attribute(attr::mk_attr_id(), self.fmtsp, - allow_dead_code); + let allow_dead_code = self.ecx.attribute(self.fmtsp, allow_dead_code); return vec!(unnamed, allow_dead_code); } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index e86dcb3d311..9dcc0877fa4 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -135,10 +135,10 @@ fn parse_inner_attrs_and_next(&mut self) // we need to get the position of this token before we bump. let Span { lo, hi, .. } = self.span; self.bump(); - ::attr::mk_sugared_doc_attr(attr::mk_attr_id(), - self.id_to_interned_str(s), - lo, - hi) + attr::mk_sugared_doc_attr(attr::mk_attr_id(), + self.id_to_interned_str(s), + lo, + hi) } _ => { break;