Skip to content

Commit d469e0d

Browse files
committed
Auto merge of rust-lang#12840 - Veykril:be-lazy, r=Veykril
internal: Use ItemTree for variant, field and module attribute collection in attrs_query Less parsing = very good, should speed up lang item collection as that basically probes attributes of all enum variants which currently triggers parsing Not fond of how this is searching for the correct index, ideally we'd map between HIR and item tree Id here but I am not sure how, storing the item tree ids in the HIR version doesn't work due to the usage of `Trace`...
2 parents 7e30ca1 + 0081ef3 commit d469e0d

File tree

5 files changed

+183
-117
lines changed

5 files changed

+183
-117
lines changed

crates/hir-def/src/adt.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ impl EnumData {
136136

137137
let enum_ = &item_tree[loc.id.value];
138138
let mut variants = Arena::new();
139-
for var_id in enum_.variants.clone() {
140-
if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
141-
let var = &item_tree[var_id];
139+
for tree_id in enum_.variants.clone() {
140+
if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
141+
let var = &item_tree[tree_id];
142142
let var_data = lower_fields(
143143
db,
144144
krate,

crates/hir-def/src/attr.rs

Lines changed: 105 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use cfg::{CfgExpr, CfgOptions};
77
use either::Either;
88
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
99
use itertools::Itertools;
10-
use la_arena::ArenaMap;
10+
use la_arena::{ArenaMap, Idx, RawIdx};
1111
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
1212
use smallvec::{smallvec, SmallVec};
1313
use syntax::{
@@ -19,12 +19,12 @@ use tt::Subtree;
1919
use crate::{
2020
db::DefDatabase,
2121
intern::Interned,
22-
item_tree::{ItemTreeId, ItemTreeNode},
23-
nameres::ModuleSource,
22+
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
23+
nameres::{ModuleOrigin, ModuleSource},
2424
path::{ModPath, PathKind},
2525
src::{HasChildSource, HasSource},
26-
AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup,
27-
MacroId, VariantId,
26+
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
27+
VariantId,
2828
};
2929

3030
/// Holds documentation
@@ -201,15 +201,23 @@ impl Attrs {
201201
db: &dyn DefDatabase,
202202
e: EnumId,
203203
) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
204-
let krate = e.lookup(db).container.krate;
205-
let src = e.child_source(db);
204+
// FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
206205
let mut res = ArenaMap::default();
207206

208-
for (id, var) in src.value.iter() {
209-
let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn ast::HasAttrs))
210-
.filter(db, krate);
211-
212-
res.insert(id, attrs)
207+
let loc = e.lookup(db);
208+
let krate = loc.container.krate;
209+
let item_tree = loc.id.item_tree(db);
210+
let enum_ = &item_tree[loc.id.value];
211+
let crate_graph = db.crate_graph();
212+
let cfg_options = &crate_graph[krate].cfg_options;
213+
214+
let mut idx = 0;
215+
for variant in enum_.variants.clone() {
216+
let attrs = item_tree.attrs(db, krate, variant.into());
217+
if attrs.is_cfg_enabled(cfg_options) {
218+
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
219+
idx += 1;
220+
}
213221
}
214222

215223
Arc::new(res)
@@ -219,18 +227,64 @@ impl Attrs {
219227
db: &dyn DefDatabase,
220228
v: VariantId,
221229
) -> Arc<ArenaMap<LocalFieldId, Attrs>> {
222-
let krate = v.module(db).krate;
223-
let src = v.child_source(db);
230+
// FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
224231
let mut res = ArenaMap::default();
225232

226-
for (id, fld) in src.value.iter() {
227-
let owner: &dyn HasAttrs = match fld {
228-
Either::Left(tuple) => tuple,
229-
Either::Right(record) => record,
230-
};
231-
let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
233+
let crate_graph = db.crate_graph();
234+
let (fields, item_tree, krate) = match v {
235+
VariantId::EnumVariantId(it) => {
236+
let e = it.parent;
237+
let loc = e.lookup(db);
238+
let krate = loc.container.krate;
239+
let item_tree = loc.id.item_tree(db);
240+
let enum_ = &item_tree[loc.id.value];
241+
242+
let cfg_options = &crate_graph[krate].cfg_options;
243+
let variant = 'tri: loop {
244+
let mut idx = 0;
245+
for variant in enum_.variants.clone() {
246+
let attrs = item_tree.attrs(db, krate, variant.into());
247+
if attrs.is_cfg_enabled(cfg_options) {
248+
if it.local_id == Idx::from_raw(RawIdx::from(idx)) {
249+
break 'tri variant;
250+
}
251+
idx += 1;
252+
}
253+
}
254+
return Arc::new(res);
255+
};
256+
(item_tree[variant].fields.clone(), item_tree, krate)
257+
}
258+
VariantId::StructId(it) => {
259+
let loc = it.lookup(db);
260+
let krate = loc.container.krate;
261+
let item_tree = loc.id.item_tree(db);
262+
let struct_ = &item_tree[loc.id.value];
263+
(struct_.fields.clone(), item_tree, krate)
264+
}
265+
VariantId::UnionId(it) => {
266+
let loc = it.lookup(db);
267+
let krate = loc.container.krate;
268+
let item_tree = loc.id.item_tree(db);
269+
let union_ = &item_tree[loc.id.value];
270+
(union_.fields.clone(), item_tree, krate)
271+
}
272+
};
232273

233-
res.insert(id, attrs);
274+
let fields = match fields {
275+
Fields::Record(fields) | Fields::Tuple(fields) => fields,
276+
Fields::Unit => return Arc::new(res),
277+
};
278+
279+
let cfg_options = &crate_graph[krate].cfg_options;
280+
281+
let mut idx = 0;
282+
for field in fields {
283+
let attrs = item_tree.attrs(db, krate, field.into());
284+
if attrs.is_cfg_enabled(cfg_options) {
285+
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
286+
idx += 1;
287+
}
234288
}
235289

236290
Arc::new(res)
@@ -243,11 +297,14 @@ impl Attrs {
243297

244298
impl Attrs {
245299
pub fn cfg(&self) -> Option<CfgExpr> {
246-
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>();
247-
match cfgs.len() {
248-
0 => None,
249-
1 => Some(cfgs.pop().unwrap()),
250-
_ => Some(CfgExpr::All(cfgs)),
300+
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
301+
let first = cfgs.next()?;
302+
match cfgs.next() {
303+
Some(second) => {
304+
let cfgs = [first, second].into_iter().chain(cfgs);
305+
Some(CfgExpr::All(cfgs.collect()))
306+
}
307+
None => Some(first),
251308
}
252309
}
253310
pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
@@ -315,25 +372,30 @@ impl AttrsWithOwner {
315372
AttrDefId::ModuleId(module) => {
316373
let def_map = module.def_map(db);
317374
let mod_data = &def_map[module.local_id];
318-
match mod_data.declaration_source(db) {
319-
Some(it) => {
320-
let raw_attrs = RawAttrs::from_attrs_owner(
321-
db,
322-
it.as_ref().map(|it| it as &dyn ast::HasAttrs),
323-
);
324-
match mod_data.definition_source(db) {
325-
InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs
326-
.merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))),
327-
_ => raw_attrs,
328-
}
375+
376+
match mod_data.origin {
377+
ModuleOrigin::File { definition, declaration_tree_id, .. } => {
378+
let decl_attrs = declaration_tree_id
379+
.item_tree(db)
380+
.raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into()))
381+
.clone();
382+
let tree = db.file_item_tree(definition.into());
383+
let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone();
384+
decl_attrs.merge(def_attrs)
385+
}
386+
ModuleOrigin::CrateRoot { definition } => {
387+
let tree = db.file_item_tree(definition.into());
388+
tree.raw_attrs(AttrOwner::TopLevel).clone()
329389
}
330-
None => RawAttrs::from_attrs_owner(
390+
ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id
391+
.item_tree(db)
392+
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
393+
.clone(),
394+
ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
331395
db,
332-
mod_data.definition_source(db).as_ref().map(|src| match src {
333-
ModuleSource::SourceFile(file) => file as &dyn ast::HasAttrs,
334-
ModuleSource::Module(module) => module as &dyn ast::HasAttrs,
335-
ModuleSource::BlockExpr(block) => block as &dyn ast::HasAttrs,
336-
}),
396+
InFile::new(block.file_id, block.to_node(db.upcast()))
397+
.as_ref()
398+
.map(|it| it as &dyn ast::HasAttrs),
337399
),
338400
}
339401
}

0 commit comments

Comments
 (0)