Skip to content

Commit 18687a9

Browse files
committedNov 26, 2013
auto merge of #10649 : sfackler/rust/multi-macro, r=alexcrichton
The majority of this change is modifying some of the `ast_visit` methods to return multiple values. It's prohibitively expensive to allocate a `~[Foo]` every time a statement, declaration, item, etc is visited, especially since the vast majority will have 0 or 1 elements. I've added a `SmallVector` class that avoids allocation in the 0 and 1 element cases to take care of that.
2 parents 35ebf03 + c403c1f commit 18687a9

File tree

13 files changed

+328
-128
lines changed

13 files changed

+328
-128
lines changed
 

‎src/librustc/front/config.rs

+12-22
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ pub fn strip_items(crate: ast::Crate,
4848
ctxt.fold_crate(crate)
4949
}
5050

51-
fn filter_item(cx: &Context, item: @ast::item) -> Option<@ast::item> {
52-
if item_in_cfg(cx, item) {
53-
Some(item)
54-
} else {
55-
None
56-
}
57-
}
58-
5951
fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
6052
-> Option<&'r ast::view_item> {
6153
if view_item_in_cfg(cx, view_item) {
@@ -66,9 +58,10 @@ fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
6658
}
6759

6860
fn fold_mod(cx: &Context, m: &ast::_mod) -> ast::_mod {
69-
let filtered_items = m.items.iter().filter_map(|a| {
70-
filter_item(cx, *a).and_then(|x| cx.fold_item(x))
71-
}).collect();
61+
let filtered_items = m.items.iter()
62+
.filter(|&a| item_in_cfg(cx, *a))
63+
.flat_map(|&x| cx.fold_item(x).move_iter())
64+
.collect();
7265
let filtered_view_items = m.view_items.iter().filter_map(|a| {
7366
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
7467
}).collect();
@@ -122,28 +115,25 @@ fn fold_item_underscore(cx: &Context, item: &ast::item_) -> ast::item_ {
122115
fold::noop_fold_item_underscore(&item, cx)
123116
}
124117

125-
fn filter_stmt(cx: &Context, stmt: @ast::Stmt) -> Option<@ast::Stmt> {
118+
fn retain_stmt(cx: &Context, stmt: @ast::Stmt) -> bool {
126119
match stmt.node {
127120
ast::StmtDecl(decl, _) => {
128121
match decl.node {
129122
ast::DeclItem(item) => {
130-
if item_in_cfg(cx, item) {
131-
Some(stmt)
132-
} else {
133-
None
134-
}
123+
item_in_cfg(cx, item)
135124
}
136-
_ => Some(stmt)
125+
_ => true
137126
}
138127
}
139-
_ => Some(stmt),
128+
_ => true
140129
}
141130
}
142131

143132
fn fold_block(cx: &Context, b: &ast::Block) -> ast::Block {
144-
let resulting_stmts = b.stmts.iter().filter_map(|a| {
145-
filter_stmt(cx, *a).and_then(|stmt| cx.fold_stmt(stmt))
146-
}).collect();
133+
let resulting_stmts = b.stmts.iter()
134+
.filter(|&a| retain_stmt(cx, *a))
135+
.flat_map(|&stmt| cx.fold_stmt(stmt).move_iter())
136+
.collect();
147137
let filtered_view_items = b.view_items.iter().filter_map(|a| {
148138
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
149139
}).collect();

‎src/librustc/front/std_inject.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use syntax::codemap;
1919
use syntax::fold::ast_fold;
2020
use syntax::fold;
2121
use syntax::opt_vec;
22+
use syntax::util::small_vector::SmallVector;
2223

2324
static STD_VERSION: &'static str = "0.9-pre";
2425

@@ -98,14 +99,14 @@ impl fold::ast_fold for StandardLibraryInjector {
9899
}
99100
}
100101

101-
fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
102+
fn fold_item(&self, item: @ast::item) -> SmallVector<@ast::item> {
102103
if !no_prelude(item.attrs) {
103104
// only recur if there wasn't `#[no_implicit_prelude];`
104105
// on this item, i.e. this means that the prelude is not
105106
// implicitly imported though the whole subtree
106107
fold::noop_fold_item(item, self)
107108
} else {
108-
Some(item)
109+
SmallVector::one(item)
109110
}
110111
}
111112

‎src/librustc/front/test.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use syntax::fold;
2626
use syntax::opt_vec;
2727
use syntax::print::pprust;
2828
use syntax::{ast, ast_util};
29+
use syntax::util::small_vector::SmallVector;
2930

3031
struct Test {
3132
span: Span,
@@ -76,7 +77,7 @@ impl fold::ast_fold for TestHarnessGenerator {
7677
}
7778
}
7879

79-
fn fold_item(&self, i: @ast::item) -> Option<@ast::item> {
80+
fn fold_item(&self, i: @ast::item) -> SmallVector<@ast::item> {
8081
self.cx.path.push(i.ident);
8182
debug!("current path: {}",
8283
ast_util::path_name_i(self.cx.path.clone()));
@@ -108,7 +109,7 @@ impl fold::ast_fold for TestHarnessGenerator {
108109

109110
let res = fold::noop_fold_item(i, self);
110111
self.cx.path.pop();
111-
return res;
112+
res
112113
}
113114

114115
fn fold_mod(&self, m: &ast::_mod) -> ast::_mod {

‎src/librustc/middle/astencode.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,8 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
347347

348348
match *ii {
349349
//hack: we're not dropping items
350-
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).unwrap()),
350+
ast::ii_item(i) => ast::ii_item(fld.fold_item(i)
351+
.expect_one("expected one item")),
351352
ast::ii_method(d, is_provided, m) =>
352353
ast::ii_method(d, is_provided, fld.fold_method(m)),
353354
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
@@ -379,7 +380,8 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
379380
xcx: xcx,
380381
};
381382
match ii {
382-
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).unwrap()),
383+
ast::ii_item(i) => ast::ii_item(fld.fold_item(i)
384+
.expect_one("expected one item")),
383385
ast::ii_method(d, is_provided, m) =>
384386
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
385387
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),

‎src/librustpkg/util.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use syntax::{ast, attr, codemap, diagnostic, fold, visit};
2222
use syntax::attr::AttrMetaMethods;
2323
use syntax::fold::ast_fold;
2424
use syntax::visit::Visitor;
25+
use syntax::util::small_vector::SmallVector;
2526
use rustc::back::link::output_type_exe;
2627
use rustc::back::link;
2728
use rustc::driver::session::{lib_crate, bin_crate};
@@ -99,7 +100,7 @@ fn fold_mod(_ctx: @mut ReadyCtx, m: &ast::_mod, fold: &CrateSetup)
99100
}
100101

101102
fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &CrateSetup)
102-
-> Option<@ast::item> {
103+
-> SmallVector<@ast::item> {
103104
ctx.path.push(item.ident);
104105

105106
let mut cmds = ~[];
@@ -142,7 +143,7 @@ struct CrateSetup {
142143
}
143144

144145
impl fold::ast_fold for CrateSetup {
145-
fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
146+
fn fold_item(&self, item: @ast::item) -> SmallVector<@ast::item> {
146147
fold_item(self.ctx, item, self)
147148
}
148149
fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {

‎src/libsyntax/ext/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use ext::expand;
1818
use parse;
1919
use parse::token;
2020
use parse::token::{ident_to_str, intern, str_to_ident};
21+
use util::small_vector::SmallVector;
2122

2223
use std::hashmap::HashMap;
2324

@@ -131,7 +132,7 @@ pub type SyntaxExpanderTTItemFunNoCtxt =
131132

132133
pub trait AnyMacro {
133134
fn make_expr(&self) -> @ast::Expr;
134-
fn make_item(&self) -> Option<@ast::item>;
135+
fn make_items(&self) -> SmallVector<@ast::item>;
135136
fn make_stmt(&self) -> @ast::Stmt;
136137
}
137138

0 commit comments

Comments
 (0)
Please sign in to comment.