auto merge of #7902 : huonw/rust/attr++, r=cmr,pcwalton

This does a number of things, but especially dramatically reduce the
number of allocations performed for operations involving attributes/
meta items:

- Converts ast::meta_item & ast::attribute and other associated enums
  to CamelCase.
- Converts several standalone functions in syntax::attr into methods,
  defined on two traits AttrMetaMethods & AttributeMethods. The former
  is common to both MetaItem and Attribute since the latter is a thin
  wrapper around the former.
- Deletes functions that are unnecessary due to iterators.
- Converts other standalone functions to use iterators and the generic
  AttrMetaMethods rather than allocating a lot of new vectors (e.g. the
  old code would have to allocate a new vector to use functions that
  operated on &[meta_item] on &[attribute].)
- Moves the core algorithm of the #[cfg] matching to syntax::attr,
  similar to find_inline_attr and find_linkage_metas.

This doesn't have much of an effect on the speed of #[cfg] stripping,
despite hugely reducing the number of allocations performed; presumably
most of the time is spent in the ast folder rather than doing attribute
checks.

Also fixes the Eq instance of MetaItem_ to correctly ignore spans, so
that `rustc --cfg 'foo(bar)'` now works.
This commit is contained in:
bors 2013-07-20 20:25:31 -07:00
commit d029ebfc5f
60 changed files with 738 additions and 821 deletions

View file

@ -15,7 +15,7 @@ use ast::{CallSugar, NoSugar, DoSugar, ForSugar};
use ast::{TyBareFn, TyClosure};
use ast::{RegionTyParamBound, TraitTyParamBound};
use ast::{provided, public, purity};
use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
use ast::{_mod, add, arg, arm, Attribute, bind_by_ref, bind_infer};
use ast::{bitand, bitor, bitxor, blk};
use ast::{blk_check_mode, box};
use ast::{crate, crate_cfg, decl, decl_item};
@ -109,12 +109,12 @@ enum restriction {
}
type arg_or_capture_item = Either<arg, ()>;
type item_info = (ident, item_, Option<~[attribute]>);
type item_info = (ident, item_, Option<~[Attribute]>);
pub enum item_or_view_item {
// Indicates a failure to parse any kind of item. The attributes are
// returned.
iovi_none(~[attribute]),
iovi_none(~[Attribute]),
iovi_item(@item),
iovi_foreign_item(@foreign_item),
iovi_view_item(view_item)
@ -242,8 +242,8 @@ macro_rules! maybe_whole (
)
fn maybe_append(lhs: ~[attribute], rhs: Option<~[attribute]>)
-> ~[attribute] {
fn maybe_append(lhs: ~[Attribute], rhs: Option<~[Attribute]>)
-> ~[Attribute] {
match rhs {
None => lhs,
Some(ref attrs) => vec::append(lhs, (*attrs))
@ -252,7 +252,7 @@ fn maybe_append(lhs: ~[attribute], rhs: Option<~[attribute]>)
struct ParsedItemsAndViewItems {
attrs_remaining: ~[attribute],
attrs_remaining: ~[Attribute],
view_items: ~[view_item],
items: ~[@item],
foreign_items: ~[@foreign_item]
@ -2959,7 +2959,7 @@ impl Parser {
// parse a structure field
fn parse_name_and_ty(&self,
pr: visibility,
attrs: ~[attribute]) -> @struct_field {
attrs: ~[Attribute]) -> @struct_field {
let lo = self.span.lo;
if !is_plain_ident(&*self.token) {
self.fatal("expected ident");
@ -2977,7 +2977,7 @@ impl Parser {
// parse a statement. may include decl.
// precondition: any attributes are parsed already
pub fn parse_stmt(&self, item_attrs: ~[attribute]) -> @stmt {
pub fn parse_stmt(&self, item_attrs: ~[Attribute]) -> @stmt {
maybe_whole!(self, nt_stmt);
fn check_expected_item(p: &Parser, found_attrs: bool) {
@ -3091,7 +3091,7 @@ impl Parser {
// parse a block. Inner attrs are allowed.
fn parse_inner_attrs_and_block(&self)
-> (~[attribute], blk) {
-> (~[Attribute], blk) {
maybe_whole!(pair_empty self, nt_block);
@ -3115,7 +3115,7 @@ impl Parser {
// parse the rest of a block expression or function body
fn parse_block_tail_(&self, lo: BytePos, s: blk_check_mode,
first_item_attrs: ~[attribute]) -> blk {
first_item_attrs: ~[Attribute]) -> blk {
let mut stmts = ~[];
let mut expr = None;
@ -3594,7 +3594,7 @@ impl Parser {
fn mk_item(&self, lo: BytePos, hi: BytePos, ident: ident,
node: item_, vis: visibility,
attrs: ~[attribute]) -> @item {
attrs: ~[Attribute]) -> @item {
@ast::item { ident: ident,
attrs: attrs,
id: self.get_id(),
@ -3825,7 +3825,7 @@ impl Parser {
// parse a structure field declaration
pub fn parse_single_struct_field(&self,
vis: visibility,
attrs: ~[attribute])
attrs: ~[Attribute])
-> @struct_field {
if self.eat_obsolete_ident("let") {
self.obsolete(*self.last_span, ObsoleteLet);
@ -3894,7 +3894,7 @@ impl Parser {
// attributes (of length 0 or 1), parse all of the items in a module
fn parse_mod_items(&self,
term: token::Token,
first_item_attrs: ~[attribute])
first_item_attrs: ~[Attribute])
-> _mod {
// parse all of the items up to closing or an attribute.
// view items are legal here.
@ -3953,7 +3953,7 @@ impl Parser {
}
// parse a `mod <foo> { ... }` or `mod <foo>;` item
fn parse_item_mod(&self, outer_attrs: &[ast::attribute]) -> item_info {
fn parse_item_mod(&self, outer_attrs: &[Attribute]) -> item_info {
let id_span = *self.span;
let id = self.parse_ident();
if *self.token == token::SEMI {
@ -3972,11 +3972,10 @@ impl Parser {
}
}
fn push_mod_path(&self, id: ident, attrs: &[ast::attribute]) {
fn push_mod_path(&self, id: ident, attrs: &[Attribute]) {
let default_path = token::interner_get(id.name);
let file_path = match ::attr::first_attr_value_str_by_name(
attrs, "path") {
let file_path = match ::attr::first_attr_value_str_by_name(attrs,
"path") {
Some(d) => d,
None => default_path
};
@ -3990,14 +3989,13 @@ impl Parser {
// read a module from a source file.
fn eval_src_mod(&self,
id: ast::ident,
outer_attrs: &[ast::attribute],
outer_attrs: &[ast::Attribute],
id_sp: span)
-> (ast::item_, ~[ast::attribute]) {
-> (ast::item_, ~[ast::Attribute]) {
let prefix = Path(self.sess.cm.span_to_filename(*self.span));
let prefix = prefix.dir_path();
let mod_path_stack = &*self.mod_path_stack;
let mod_path = Path(".").push_many(*mod_path_stack);
let default_path = token::interner_get(id.name).to_owned() + ".rs";
let file_path = match ::attr::first_attr_value_str_by_name(
outer_attrs, "path") {
Some(d) => {
@ -4008,7 +4006,7 @@ impl Parser {
path
}
}
None => mod_path.push(default_path)
None => mod_path.push(token::interner_get(id.name) + ".rs") // default
};
self.eval_src_mod_from_path(prefix,
@ -4020,8 +4018,8 @@ impl Parser {
fn eval_src_mod_from_path(&self,
prefix: Path,
path: Path,
outer_attrs: ~[ast::attribute],
id_sp: span) -> (ast::item_, ~[ast::attribute]) {
outer_attrs: ~[ast::Attribute],
id_sp: span) -> (ast::item_, ~[ast::Attribute]) {
let full_path = if path.is_absolute {
path
@ -4057,17 +4055,10 @@ impl Parser {
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
self.sess.included_mod_stack.pop();
return (ast::item_mod(m0), mod_attrs);
fn cdir_path_opt(default: @str, attrs: ~[ast::attribute]) -> @str {
match ::attr::first_attr_value_str_by_name(attrs, "path") {
Some(d) => d,
None => default
}
}
}
// parse a function declaration from a foreign module
fn parse_item_foreign_fn(&self, attrs: ~[attribute]) -> @foreign_item {
fn parse_item_foreign_fn(&self, attrs: ~[Attribute]) -> @foreign_item {
let lo = self.span.lo;
let vis = self.parse_visibility();
let purity = self.parse_fn_purity();
@ -4085,7 +4076,7 @@ impl Parser {
// parse a const definition from a foreign module
fn parse_item_foreign_const(&self, vis: ast::visibility,
attrs: ~[attribute]) -> @foreign_item {
attrs: ~[Attribute]) -> @foreign_item {
let lo = self.span.lo;
// XXX: Obsolete; remove after snap.
@ -4130,7 +4121,7 @@ impl Parser {
fn parse_foreign_mod_items(&self,
sort: ast::foreign_mod_sort,
abis: AbiSet,
first_item_attrs: ~[attribute])
first_item_attrs: ~[Attribute])
-> foreign_mod {
let ParsedItemsAndViewItems {
attrs_remaining: attrs_remaining,
@ -4156,7 +4147,7 @@ impl Parser {
lo: BytePos,
opt_abis: Option<AbiSet>,
visibility: visibility,
attrs: ~[attribute],
attrs: ~[Attribute],
items_allowed: bool)
-> item_or_view_item {
let mut must_be_named_mod = false;
@ -4437,7 +4428,7 @@ impl Parser {
// NB: this function no longer parses the items inside an
// extern mod.
fn parse_item_or_view_item(&self,
attrs: ~[attribute],
attrs: ~[Attribute],
macros_allowed: bool)
-> item_or_view_item {
maybe_whole!(iovi self, nt_item);
@ -4569,7 +4560,7 @@ impl Parser {
// parse a foreign item; on failure, return iovi_none.
fn parse_foreign_item(&self,
attrs: ~[attribute],
attrs: ~[Attribute],
macros_allowed: bool)
-> item_or_view_item {
maybe_whole!(iovi self, nt_item);
@ -4594,7 +4585,7 @@ impl Parser {
// this is the fall-through for parsing items.
fn parse_macro_use_or_failure(
&self,
attrs: ~[attribute],
attrs: ~[Attribute],
macros_allowed: bool,
lo : BytePos,
visibility : visibility
@ -4656,7 +4647,7 @@ impl Parser {
return iovi_none(attrs);
}
pub fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> {
pub fn parse_item(&self, attrs: ~[Attribute]) -> Option<@ast::item> {
match self.parse_item_or_view_item(attrs, true) {
iovi_none(_) =>
None,
@ -4793,7 +4784,7 @@ impl Parser {
// parse a view item.
fn parse_view_item(
&self,
attrs: ~[attribute],
attrs: ~[Attribute],
vis: visibility
) -> view_item {
let lo = self.span.lo;
@ -4819,7 +4810,7 @@ impl Parser {
// - mod_items uses extern_mod_allowed = true
// - block_tail_ uses extern_mod_allowed = false
fn parse_items_and_view_items(&self,
first_item_attrs: ~[attribute],
first_item_attrs: ~[Attribute],
mut extern_mod_allowed: bool,
macros_allowed: bool)
-> ParsedItemsAndViewItems {
@ -4901,7 +4892,7 @@ impl Parser {
// Parses a sequence of foreign items. Stops when it finds program
// text that can't be parsed as an item
fn parse_foreign_items(&self, first_item_attrs: ~[attribute],
fn parse_foreign_items(&self, first_item_attrs: ~[Attribute],
macros_allowed: bool)
-> ParsedItemsAndViewItems {
let mut attrs = vec::append(first_item_attrs,