Skip to content

Commit 2596bc1

Browse files
committed
Auto merge of #58061 - nnethercote:overhaul-syntax-Folder, r=petrochenkov
Overhaul `syntax::fold::Folder`. This PR changes `syntax::fold::Folder` from a functional style (where most methods take a `T` and produce a new `T`) to a more imperative style (where most methods take and modify a `&mut T`), and renames it `syntax::mut_visit::MutVisitor`. This makes the code faster and more concise.
2 parents 0e5a209 + bfcbd23 commit 2596bc1

File tree

24 files changed

+1791
-2004
lines changed

24 files changed

+1791
-2004
lines changed

src/librustc_allocator/expand.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use syntax::{
1616
expand::ExpansionConfig,
1717
hygiene::{self, Mark, SyntaxContext},
1818
},
19-
fold::{self, Folder},
19+
mut_visit::{self, MutVisitor},
2020
parse::ParseSess,
2121
ptr::P,
2222
symbol::Symbol
@@ -28,18 +28,18 @@ use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
2828
pub fn modify(
2929
sess: &ParseSess,
3030
resolver: &mut dyn Resolver,
31-
krate: Crate,
31+
krate: &mut Crate,
3232
crate_name: String,
3333
handler: &rustc_errors::Handler,
34-
) -> ast::Crate {
34+
) {
3535
ExpandAllocatorDirectives {
3636
handler,
3737
sess,
3838
resolver,
3939
found: false,
4040
crate_name: Some(crate_name),
4141
in_submod: -1, // -1 to account for the "root" module
42-
}.fold_crate(krate)
42+
}.visit_crate(krate);
4343
}
4444

4545
struct ExpandAllocatorDirectives<'a> {
@@ -54,14 +54,14 @@ struct ExpandAllocatorDirectives<'a> {
5454
in_submod: isize,
5555
}
5656

57-
impl<'a> Folder for ExpandAllocatorDirectives<'a> {
58-
fn fold_item(&mut self, item: P<Item>) -> SmallVec<[P<Item>; 1]> {
57+
impl<'a> MutVisitor for ExpandAllocatorDirectives<'a> {
58+
fn flat_map_item(&mut self, item: P<Item>) -> SmallVec<[P<Item>; 1]> {
5959
debug!("in submodule {}", self.in_submod);
6060

6161
let name = if attr::contains_name(&item.attrs, "global_allocator") {
6262
"global_allocator"
6363
} else {
64-
return fold::noop_fold_item(item, self);
64+
return mut_visit::noop_flat_map_item(item, self);
6565
};
6666
match item.node {
6767
ItemKind::Static(..) => {}
@@ -139,25 +139,24 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
139139
let name = f.kind.fn_name("allocator_abi");
140140
let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name));
141141
let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
142-
let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();
142+
let module = f.cx.monotonic_expander().flat_map_item(module).pop().unwrap();
143143

144144
// Return the item and new submodule
145145
smallvec![item, module]
146146
}
147147

148148
// If we enter a submodule, take note.
149-
fn fold_mod(&mut self, m: Mod) -> Mod {
149+
fn visit_mod(&mut self, m: &mut Mod) {
150150
debug!("enter submodule");
151151
self.in_submod += 1;
152-
let ret = fold::noop_fold_mod(m, self);
152+
mut_visit::noop_visit_mod(m, self);
153153
self.in_submod -= 1;
154154
debug!("exit submodule");
155-
ret
156155
}
157156

158-
// `fold_mac` is disabled by default. Enable it here.
159-
fn fold_mac(&mut self, mac: Mac) -> Mac {
160-
fold::noop_fold_mac(mac, self)
157+
// `visit_mac` is disabled by default. Enable it here.
158+
fn visit_mac(&mut self, mac: &mut Mac) {
159+
mut_visit::noop_visit_mac(mac, self)
161160
}
162161
}
163162

src/librustc_data_structures/thin_vec.rs

+9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ impl<T> ::std::ops::Deref for ThinVec<T> {
3939
}
4040
}
4141

42+
impl<T> ::std::ops::DerefMut for ThinVec<T> {
43+
fn deref_mut(&mut self) -> &mut [T] {
44+
match *self {
45+
ThinVec(None) => &mut [],
46+
ThinVec(Some(ref mut vec)) => vec,
47+
}
48+
}
49+
}
50+
4251
impl<T> Extend<T> for ThinVec<T> {
4352
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
4453
match *self {

src/librustc_driver/driver.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_typeck as typeck;
3232
use syntax::{self, ast, attr, diagnostics, visit};
3333
use syntax::early_buffered_lints::BufferedEarlyLint;
3434
use syntax::ext::base::ExtCtxt;
35-
use syntax::fold::Folder;
35+
use syntax::mut_visit::MutVisitor;
3636
use syntax::parse::{self, PResult};
3737
use syntax::util::node_count::NodeCounter;
3838
use syntax::util::lev_distance::find_best_match_for_name;
@@ -1000,12 +1000,12 @@ where
10001000
});
10011001
sess.profiler(|p| p.end_activity(ProfileCategory::Expansion));
10021002

1003-
krate = time(sess, "maybe building test harness", || {
1003+
time(sess, "maybe building test harness", || {
10041004
syntax::test::modify_for_testing(
10051005
&sess.parse_sess,
10061006
&mut resolver,
10071007
sess.opts.test,
1008-
krate,
1008+
&mut krate,
10091009
sess.diagnostic(),
10101010
&sess.features_untracked(),
10111011
)
@@ -1014,7 +1014,7 @@ where
10141014
// If we're actually rustdoc then there's no need to actually compile
10151015
// anything, so switch everything to just looping
10161016
if sess.opts.actually_rustdoc {
1017-
krate = ReplaceBodyWithLoop::new(sess).fold_crate(krate);
1017+
ReplaceBodyWithLoop::new(sess).visit_crate(&mut krate);
10181018
}
10191019

10201020
let (has_proc_macro_decls, has_global_allocator) = time(sess, "AST validation", || {
@@ -1045,11 +1045,11 @@ where
10451045

10461046
if has_global_allocator {
10471047
// Expand global allocators, which are treated as an in-tree proc macro
1048-
krate = time(sess, "creating allocators", || {
1048+
time(sess, "creating allocators", || {
10491049
allocator::expand::modify(
10501050
&sess.parse_sess,
10511051
&mut resolver,
1052-
krate,
1052+
&mut krate,
10531053
crate_name.to_string(),
10541054
sess.diagnostic(),
10551055
)

src/librustc_driver/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,9 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
870870
control.after_hir_lowering.stop = Compilation::Stop;
871871

872872
control.after_parse.callback = box move |state| {
873-
state.krate = Some(pretty::fold_crate(state.session,
874-
state.krate.take().unwrap(),
875-
ppm));
873+
let mut krate = state.krate.take().unwrap();
874+
pretty::visit_crate(state.session, &mut krate, ppm);
875+
state.krate = Some(krate);
876876
};
877877
control.after_hir_lowering.callback = box move |state| {
878878
pretty::print_after_hir_lowering(state.session,
@@ -891,7 +891,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
891891
control.after_parse.stop = Compilation::Stop;
892892

893893
control.after_parse.callback = box move |state| {
894-
let krate = pretty::fold_crate(state.session, state.krate.take().unwrap(), ppm);
894+
let mut krate = state.krate.take().unwrap();
895+
pretty::visit_crate(state.session, &mut krate, ppm);
895896
pretty::print_after_parsing(state.session,
896897
state.input,
897898
&krate,

src/librustc_driver/pretty.rs

+20-22
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_metadata::cstore::CStore;
1616
use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
1717

1818
use syntax::ast::{self, BlockCheckMode};
19-
use syntax::fold::{self, Folder};
19+
use syntax::mut_visit::{*, MutVisitor, visit_clobber};
2020
use syntax::print::{pprust};
2121
use syntax::print::pprust::PrintState;
2222
use syntax::ptr::P;
@@ -28,6 +28,7 @@ use smallvec::SmallVec;
2828
use std::cell::Cell;
2929
use std::fs::File;
3030
use std::io::{self, Write};
31+
use std::ops::DerefMut;
3132
use std::option;
3233
use std::path::Path;
3334
use std::str::FromStr;
@@ -703,42 +704,42 @@ impl<'a> ReplaceBodyWithLoop<'a> {
703704
}
704705
}
705706

706-
impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
707-
fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind {
707+
impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> {
708+
fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
708709
let is_const = match i {
709710
ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
710711
ast::ItemKind::Fn(ref decl, ref header, _, _) =>
711712
header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
712713
_ => false,
713714
};
714-
self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
715+
self.run(is_const, |s| noop_visit_item_kind(i, s))
715716
}
716717

717-
fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
718+
fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
718719
let is_const = match i.node {
719720
ast::TraitItemKind::Const(..) => true,
720721
ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
721722
header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
722723
_ => false,
723724
};
724-
self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
725+
self.run(is_const, |s| noop_flat_map_trait_item(i, s))
725726
}
726727

727-
fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
728+
fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
728729
let is_const = match i.node {
729730
ast::ImplItemKind::Const(..) => true,
730731
ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
731732
header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
732733
_ => false,
733734
};
734-
self.run(is_const, |s| fold::noop_fold_impl_item(i, s))
735+
self.run(is_const, |s| noop_flat_map_impl_item(i, s))
735736
}
736737

737-
fn fold_anon_const(&mut self, c: ast::AnonConst) -> ast::AnonConst {
738-
self.run(true, |s| fold::noop_fold_anon_const(c, s))
738+
fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
739+
self.run(true, |s| noop_visit_anon_const(c, s))
739740
}
740741

741-
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
742+
fn visit_block(&mut self, b: &mut P<ast::Block>) {
742743
fn stmt_to_block(rules: ast::BlockCheckMode,
743744
s: Option<ast::Stmt>,
744745
sess: &Session) -> ast::Block {
@@ -780,14 +781,14 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
780781
};
781782

782783
if self.within_static_or_const {
783-
fold::noop_fold_block(b, self)
784+
noop_visit_block(b, self)
784785
} else {
785-
b.map(|b| {
786+
visit_clobber(b.deref_mut(), |b| {
786787
let mut stmts = vec![];
787788
for s in b.stmts {
788789
let old_blocks = self.nested_blocks.replace(vec![]);
789790

790-
stmts.extend(self.fold_stmt(s).into_iter().filter(|s| s.is_item()));
791+
stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item()));
791792

792793
// we put a Some in there earlier with that replace(), so this is valid
793794
let new_blocks = self.nested_blocks.take().unwrap();
@@ -818,9 +819,9 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
818819
}
819820

820821
// in general the pretty printer processes unexpanded code, so
821-
// we override the default `fold_mac` method which panics.
822-
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
823-
fold::noop_fold_mac(mac, self)
822+
// we override the default `visit_mac` method which panics.
823+
fn visit_mac(&mut self, mac: &mut ast::Mac) {
824+
noop_visit_mac(mac, self)
824825
}
825826
}
826827

@@ -889,12 +890,9 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
889890
}
890891
}
891892

892-
pub fn fold_crate(sess: &Session, krate: ast::Crate, ppm: PpMode) -> ast::Crate {
893+
pub fn visit_crate(sess: &Session, krate: &mut ast::Crate, ppm: PpMode) {
893894
if let PpmSource(PpmEveryBodyLoops) = ppm {
894-
let mut fold = ReplaceBodyWithLoop::new(sess);
895-
fold.fold_crate(krate)
896-
} else {
897-
krate
895+
ReplaceBodyWithLoop::new(sess).visit_crate(krate);
898896
}
899897
}
900898

0 commit comments

Comments
 (0)