Skip to content

Commit dbd7c1d

Browse files
committed
Use arenas for AST
This makes some code DRYer since we don't need to use Cows and have different code paths for items with different lifetimes.
1 parent b4b9b7d commit dbd7c1d

File tree

3 files changed

+38
-68
lines changed

3 files changed

+38
-68
lines changed

src/formatting.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::collections::HashMap;
44
use std::io::{self, Write};
55
use std::time::{Duration, Instant};
66

7+
use rustc_arena::TypedArena;
78
use rustc_ast::ast;
89
use rustc_span::Span;
910

@@ -131,7 +132,11 @@ fn format_project<T: FormatHandler>(
131132
};
132133

133134
let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
135+
let item_arena = TypedArena::default();
136+
let mod_kind_arena = TypedArena::default();
134137
let files = modules::ModResolver::new(
138+
&item_arena,
139+
&mod_kind_arena,
135140
&context.parse_session,
136141
directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
137142
!input_is_stdin && !config.skip_children(),

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern crate lazy_static;
1111
extern crate tracing;
1212

1313
// N.B. these crates are loaded from the sysroot, so they need extern crate.
14+
extern crate rustc_arena;
1415
extern crate rustc_ast;
1516
extern crate rustc_ast_pretty;
1617
extern crate rustc_builtin_macros;

src/modules.rs

Lines changed: 32 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use std::borrow::Cow;
21
use std::collections::BTreeMap;
32
use std::path::{Path, PathBuf};
43

4+
use rustc_arena::TypedArena;
55
use rustc_ast::ast;
6+
use rustc_ast::ptr::P;
67
use rustc_ast::visit::Visitor;
78
use rustc_span::symbol::{self, sym, Symbol};
89
use rustc_span::Span;
9-
use thin_vec::ThinVec;
1010
use thiserror::Error;
1111

1212
use crate::attr::MetaVisitor;
@@ -25,17 +25,17 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
2525
/// Represents module with its inner attributes.
2626
#[derive(Debug, Clone)]
2727
pub(crate) struct Module<'a> {
28-
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
29-
pub(crate) items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
28+
ast_mod_kind: Option<&'a ast::ModKind>,
29+
pub(crate) items: &'a [rustc_ast::ptr::P<ast::Item>],
3030
inner_attr: ast::AttrVec,
3131
pub(crate) span: Span,
3232
}
3333

3434
impl<'a> Module<'a> {
3535
pub(crate) fn new(
3636
mod_span: Span,
37-
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
38-
mod_items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
37+
ast_mod_kind: Option<&'a ast::ModKind>,
38+
mod_items: &'a [rustc_ast::ptr::P<ast::Item>],
3939
mod_attrs: &[ast::Attribute],
4040
) -> Self {
4141
let inner_attr = mod_attrs
@@ -58,6 +58,8 @@ impl<'a> Module<'a> {
5858

5959
/// Maps each module to the corresponding file.
6060
pub(crate) struct ModResolver<'ast, 'sess> {
61+
item_arena: &'ast TypedArena<P<ast::Item>>,
62+
mod_kind_arena: &'ast TypedArena<ast::ModKind>,
6163
parse_sess: &'sess ParseSess,
6264
directory: Directory,
6365
file_map: FileModMap<'ast>,
@@ -100,11 +102,15 @@ enum SubModKind<'ast> {
100102
impl<'ast, 'sess> ModResolver<'ast, 'sess> {
101103
/// Creates a new `ModResolver`.
102104
pub(crate) fn new(
105+
item_arena: &'ast TypedArena<P<ast::Item>>,
106+
mod_kind_arena: &'ast TypedArena<ast::ModKind>,
103107
parse_sess: &'sess ParseSess,
104108
directory_ownership: DirectoryOwnership,
105109
recursive: bool,
106110
) -> Self {
107111
ModResolver {
112+
item_arena,
113+
mod_kind_arena,
108114
directory: Directory {
109115
path: PathBuf::new(),
110116
ownership: directory_ownership,
@@ -128,7 +134,7 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
128134

129135
// Skip visiting sub modules when the input is from stdin.
130136
if self.recursive {
131-
self.visit_mod_from_ast(&krate.items)?;
137+
self.visit_items(&krate.items)?;
132138
}
133139

134140
let snippet_provider = self.parse_sess.snippet_provider(krate.spans.inner_span);
@@ -138,7 +144,7 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
138144
Module::new(
139145
mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
140146
None,
141-
Cow::Borrowed(&krate.items),
147+
&krate.items,
142148
&krate.attrs,
143149
),
144150
);
@@ -149,66 +155,28 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
149155
fn visit_cfg_if(&mut self, item: &ast::Item) -> Result<(), ModuleResolutionError> {
150156
let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess);
151157
visitor.visit_item(item);
152-
self.visit_mod_outside_ast(&visitor.items)?;
158+
let items = self.item_arena.alloc_from_iter(visitor.items);
159+
self.visit_items(&*items)?;
153160
Ok(())
154161
}
155162

156-
/// Visit modules defined inside macro calls.
157-
fn visit_mod_outside_ast(
158-
&mut self,
159-
items: &[rustc_ast::ptr::P<ast::Item>],
160-
) -> Result<(), ModuleResolutionError> {
161-
for item in items {
162-
if is_cfg_if(item) {
163-
self.visit_cfg_if(item)?;
164-
continue;
165-
}
166-
167-
if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
168-
let span = item.span;
169-
self.visit_sub_mod(
170-
&item,
171-
Module::new(
172-
span,
173-
Some(Cow::Owned(sub_mod_kind.clone())),
174-
Cow::Owned(ThinVec::new()),
175-
&[],
176-
),
177-
)?;
178-
}
179-
}
180-
Ok(())
181-
}
182-
183-
/// Visit modules from AST.
184-
fn visit_mod_from_ast(
163+
fn visit_items(
185164
&mut self,
186165
items: &'ast [rustc_ast::ptr::P<ast::Item>],
187166
) -> Result<(), ModuleResolutionError> {
188167
for item in items {
189168
if is_cfg_if(item) {
190169
self.visit_cfg_if(item)?;
191-
}
192-
193-
if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
194-
let span = item.span;
195-
self.visit_sub_mod(
196-
item,
197-
Module::new(
198-
span,
199-
Some(Cow::Borrowed(sub_mod_kind)),
200-
Cow::Owned(ThinVec::new()),
201-
&[],
202-
),
203-
)?;
170+
} else if let ast::ItemKind::Mod(_, sub_mod_kind) = &item.kind {
171+
self.visit_sub_mod(&item, Module::new(item.span, Some(sub_mod_kind), &[], &[]))?;
204172
}
205173
}
206174
Ok(())
207175
}
208176

209177
fn visit_sub_mod(
210178
&mut self,
211-
item: &ast::Item,
179+
item: &'ast ast::Item,
212180
sub_mod: Module<'ast>,
213181
) -> Result<(), ModuleResolutionError> {
214182
if contains_skip(&item.attrs) {
@@ -286,14 +254,10 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
286254
&mut self,
287255
sub_mod: Module<'ast>,
288256
) -> Result<(), ModuleResolutionError> {
289-
match (sub_mod.ast_mod_kind, sub_mod.items) {
290-
(Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
291-
self.visit_mod_from_ast(items)
292-
}
293-
(Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
294-
self.visit_mod_outside_ast(&items)
295-
}
296-
(_, _) => Ok(()),
257+
if let Some(ast::ModKind::Loaded(items, _, _)) = sub_mod.ast_mod_kind {
258+
self.visit_items(items)
259+
} else {
260+
self.visit_items(&sub_mod.items)
297261
}
298262
}
299263

@@ -319,8 +283,8 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
319283
DirectoryOwnership::Owned { relative: None },
320284
Module::new(
321285
span,
322-
Some(Cow::Owned(ast::ModKind::Unloaded)),
323-
Cow::Owned(items),
286+
Some(self.mod_kind_arena.alloc(ast::ModKind::Unloaded)),
287+
self.item_arena.alloc_from_iter(items),
324288
&attrs,
325289
),
326290
))),
@@ -369,8 +333,8 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
369333
dir_ownership,
370334
Module::new(
371335
span,
372-
Some(Cow::Owned(ast::ModKind::Unloaded)),
373-
Cow::Owned(items),
336+
Some(self.mod_kind_arena.alloc(ast::ModKind::Unloaded)),
337+
self.item_arena.alloc_from_iter(items),
374338
&attrs,
375339
),
376340
)))
@@ -381,8 +345,8 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
381345
dir_ownership,
382346
Module::new(
383347
span,
384-
Some(Cow::Owned(ast::ModKind::Unloaded)),
385-
Cow::Owned(items),
348+
Some(self.mod_kind_arena.alloc(ast::ModKind::Unloaded)),
349+
self.item_arena.alloc_from_iter(items),
386350
&attrs,
387351
),
388352
));
@@ -519,8 +483,8 @@ impl<'ast, 'sess> ModResolver<'ast, 'sess> {
519483
DirectoryOwnership::Owned { relative: None },
520484
Module::new(
521485
span,
522-
Some(Cow::Owned(ast::ModKind::Unloaded)),
523-
Cow::Owned(items),
486+
Some(self.mod_kind_arena.alloc(ast::ModKind::Unloaded)),
487+
self.item_arena.alloc_from_iter(items),
524488
&attrs,
525489
),
526490
))

0 commit comments

Comments
 (0)