Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/adt.rs6
-rw-r--r--crates/hir-def/src/attr.rs148
-rw-r--r--crates/hir-def/src/data.rs117
-rw-r--r--crates/hir-def/src/nameres.rs6
-rw-r--r--crates/hir-def/src/nameres/collector.rs23
5 files changed, 183 insertions, 117 deletions
diff --git a/crates/hir-def/src/adt.rs b/crates/hir-def/src/adt.rs
index 6ba70a2df6..277135d6dc 100644
--- a/crates/hir-def/src/adt.rs
+++ b/crates/hir-def/src/adt.rs
@@ -136,9 +136,9 @@ impl EnumData {
let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
- for var_id in enum_.variants.clone() {
- if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
- let var = &item_tree[var_id];
+ for tree_id in enum_.variants.clone() {
+ if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
+ let var = &item_tree[tree_id];
let var_data = lower_fields(
db,
krate,
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index fd44493076..8a6b6f3eff 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -7,7 +7,7 @@ use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
use itertools::Itertools;
-use la_arena::ArenaMap;
+use la_arena::{ArenaMap, Idx, RawIdx};
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
use smallvec::{smallvec, SmallVec};
use syntax::{
@@ -19,12 +19,12 @@ use tt::Subtree;
use crate::{
db::DefDatabase,
intern::Interned,
- item_tree::{ItemTreeId, ItemTreeNode},
- nameres::ModuleSource,
+ item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
+ nameres::{ModuleOrigin, ModuleSource},
path::{ModPath, PathKind},
src::{HasChildSource, HasSource},
- AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup,
- MacroId, VariantId,
+ AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
+ VariantId,
};
/// Holds documentation
@@ -201,15 +201,23 @@ impl Attrs {
db: &dyn DefDatabase,
e: EnumId,
) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
- let krate = e.lookup(db).container.krate;
- let src = e.child_source(db);
+ // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
let mut res = ArenaMap::default();
- for (id, var) in src.value.iter() {
- let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn ast::HasAttrs))
- .filter(db, krate);
-
- res.insert(id, attrs)
+ let loc = e.lookup(db);
+ let krate = loc.container.krate;
+ let item_tree = loc.id.item_tree(db);
+ let enum_ = &item_tree[loc.id.value];
+ let crate_graph = db.crate_graph();
+ let cfg_options = &crate_graph[krate].cfg_options;
+
+ let mut idx = 0;
+ for variant in enum_.variants.clone() {
+ let attrs = item_tree.attrs(db, krate, variant.into());
+ if attrs.is_cfg_enabled(cfg_options) {
+ res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
+ idx += 1;
+ }
}
Arc::new(res)
@@ -219,18 +227,64 @@ impl Attrs {
db: &dyn DefDatabase,
v: VariantId,
) -> Arc<ArenaMap<LocalFieldId, Attrs>> {
- let krate = v.module(db).krate;
- let src = v.child_source(db);
+ // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
let mut res = ArenaMap::default();
- for (id, fld) in src.value.iter() {
- let owner: &dyn HasAttrs = match fld {
- Either::Left(tuple) => tuple,
- Either::Right(record) => record,
- };
- let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
+ let crate_graph = db.crate_graph();
+ let (fields, item_tree, krate) = match v {
+ VariantId::EnumVariantId(it) => {
+ let e = it.parent;
+ let loc = e.lookup(db);
+ let krate = loc.container.krate;
+ let item_tree = loc.id.item_tree(db);
+ let enum_ = &item_tree[loc.id.value];
+
+ let cfg_options = &crate_graph[krate].cfg_options;
+ let variant = 'tri: loop {
+ let mut idx = 0;
+ for variant in enum_.variants.clone() {
+ let attrs = item_tree.attrs(db, krate, variant.into());
+ if attrs.is_cfg_enabled(cfg_options) {
+ if it.local_id == Idx::from_raw(RawIdx::from(idx)) {
+ break 'tri variant;
+ }
+ idx += 1;
+ }
+ }
+ return Arc::new(res);
+ };
+ (item_tree[variant].fields.clone(), item_tree, krate)
+ }
+ VariantId::StructId(it) => {
+ let loc = it.lookup(db);
+ let krate = loc.container.krate;
+ let item_tree = loc.id.item_tree(db);
+ let struct_ = &item_tree[loc.id.value];
+ (struct_.fields.clone(), item_tree, krate)
+ }
+ VariantId::UnionId(it) => {
+ let loc = it.lookup(db);
+ let krate = loc.container.krate;
+ let item_tree = loc.id.item_tree(db);
+ let union_ = &item_tree[loc.id.value];
+ (union_.fields.clone(), item_tree, krate)
+ }
+ };
- res.insert(id, attrs);
+ let fields = match fields {
+ Fields::Record(fields) | Fields::Tuple(fields) => fields,
+ Fields::Unit => return Arc::new(res),
+ };
+
+ let cfg_options = &crate_graph[krate].cfg_options;
+
+ let mut idx = 0;
+ for field in fields {
+ let attrs = item_tree.attrs(db, krate, field.into());
+ if attrs.is_cfg_enabled(cfg_options) {
+ res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
+ idx += 1;
+ }
}
Arc::new(res)
@@ -243,11 +297,14 @@ impl Attrs {
impl Attrs {
pub fn cfg(&self) -> Option<CfgExpr> {
- let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>();
- match cfgs.len() {
- 0 => None,
- 1 => Some(cfgs.pop().unwrap()),
- _ => Some(CfgExpr::All(cfgs)),
+ let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
+ let first = cfgs.next()?;
+ match cfgs.next() {
+ Some(second) => {
+ let cfgs = [first, second].into_iter().chain(cfgs);
+ Some(CfgExpr::All(cfgs.collect()))
+ }
+ None => Some(first),
}
}
pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
@@ -315,25 +372,30 @@ impl AttrsWithOwner {
AttrDefId::ModuleId(module) => {
let def_map = module.def_map(db);
let mod_data = &def_map[module.local_id];
- match mod_data.declaration_source(db) {
- Some(it) => {
- let raw_attrs = RawAttrs::from_attrs_owner(
- db,
- it.as_ref().map(|it| it as &dyn ast::HasAttrs),
- );
- match mod_data.definition_source(db) {
- InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs
- .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))),
- _ => raw_attrs,
- }
+
+ match mod_data.origin {
+ ModuleOrigin::File { definition, declaration_tree_id, .. } => {
+ let decl_attrs = declaration_tree_id
+ .item_tree(db)
+ .raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into()))
+ .clone();
+ let tree = db.file_item_tree(definition.into());
+ let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone();
+ decl_attrs.merge(def_attrs)
+ }
+ ModuleOrigin::CrateRoot { definition } => {
+ let tree = db.file_item_tree(definition.into());
+ tree.raw_attrs(AttrOwner::TopLevel).clone()
}
- None => RawAttrs::from_attrs_owner(
+ ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id
+ .item_tree(db)
+ .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
+ .clone(),
+ ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
db,
- mod_data.definition_source(db).as_ref().map(|src| match src {
- ModuleSource::SourceFile(file) => file as &dyn ast::HasAttrs,
- ModuleSource::Module(module) => module as &dyn ast::HasAttrs,
- ModuleSource::BlockExpr(block) => block as &dyn ast::HasAttrs,
- }),
+ InFile::new(block.file_id, block.to_node(db.upcast()))
+ .as_ref()
+ .map(|it| it as &dyn ast::HasAttrs),
),
}
}
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index ca15e7c410..4309411419 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -1,8 +1,9 @@
//! Contains basic data about various HIR declarations.
-use std::{mem, sync::Arc};
+use std::sync::Arc;
-use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
+use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind};
+use smallvec::SmallVec;
use syntax::ast;
use crate::{
@@ -10,13 +11,13 @@ use crate::{
body::{Expander, Mark},
db::DefDatabase,
intern::Interned,
- item_tree::{self, AssocItem, FnFlags, ItemTreeId, ModItem, Param, TreeId},
+ item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
nameres::{attr_resolution::ResolvedAttr, DefMap},
type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
- Intern, ItemContainerId, Lookup, Macro2Id, MacroRulesId, ModuleId, ProcMacroId, StaticId,
- TraitId, TypeAliasId, TypeAliasLoc,
+ Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId, ProcMacroId,
+ StaticId, TraitId, TypeAliasId, TypeAliasLoc,
};
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -209,9 +210,9 @@ pub struct TraitData {
impl TraitData {
pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
- let tr_loc = tr.lookup(db);
- let item_tree = tr_loc.id.item_tree(db);
- let tr_def = &item_tree[tr_loc.id.value];
+ let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
+ let item_tree = tree_id.item_tree(db);
+ let tr_def = &item_tree[tree_id.value];
let _cx = stdx::panic_context::enter(format!(
"trait_data_query({:?} -> {:?} -> {:?})",
tr, tr_loc, tr_def
@@ -219,25 +220,21 @@ impl TraitData {
let name = tr_def.name.clone();
let is_auto = tr_def.is_auto;
let is_unsafe = tr_def.is_unsafe;
- let module_id = tr_loc.container;
let visibility = item_tree[tr_def.visibility].clone();
let skip_array_during_method_dispatch = item_tree
- .attrs(db, tr_loc.container.krate(), ModItem::from(tr_loc.id.value).into())
+ .attrs(db, module_id.krate(), ModItem::from(tree_id.value).into())
.by_key("rustc_skip_array_during_method_dispatch")
.exists();
- let mut collector = AssocItemCollector::new(
- db,
- module_id,
- tr_loc.id.file_id(),
- ItemContainerId::TraitId(tr),
- );
- collector.collect(tr_loc.id.tree_id(), &tr_def.items);
+ let mut collector =
+ AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
+ collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
+ let (items, attribute_calls) = collector.finish();
Arc::new(TraitData {
name,
- attribute_calls: collector.take_attr_calls(),
- items: collector.items,
+ attribute_calls,
+ items,
is_auto,
is_unsafe,
visibility,
@@ -284,25 +281,20 @@ pub struct ImplData {
impl ImplData {
pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
let _p = profile::span("impl_data_query");
- let impl_loc = id.lookup(db);
+ let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
- let item_tree = impl_loc.id.item_tree(db);
- let impl_def = &item_tree[impl_loc.id.value];
+ let item_tree = tree_id.item_tree(db);
+ let impl_def = &item_tree[tree_id.value];
let target_trait = impl_def.target_trait.clone();
let self_ty = impl_def.self_ty.clone();
let is_negative = impl_def.is_negative;
- let module_id = impl_loc.container;
- let mut collector = AssocItemCollector::new(
- db,
- module_id,
- impl_loc.id.file_id(),
- ItemContainerId::ImplId(id),
- );
- collector.collect(impl_loc.id.tree_id(), &impl_def.items);
+ let mut collector =
+ AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
+ collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
- let attribute_calls = collector.take_attr_calls();
- let items = collector.items.into_iter().map(|(_, item)| item).collect();
+ let (items, attribute_calls) = collector.finish();
+ let items = items.into_iter().map(|(_, item)| item).collect();
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls })
}
@@ -463,18 +455,19 @@ impl<'a> AssocItemCollector<'a> {
}
}
- fn take_attr_calls(&mut self) -> Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>> {
- let attribute_calls = mem::take(&mut self.attr_calls);
- if attribute_calls.is_empty() {
- None
- } else {
- Some(Box::new(attribute_calls))
- }
+ fn finish(
+ self,
+ ) -> (Vec<(Name, AssocItemId)>, Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>) {
+ (
+ self.items,
+ if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
+ )
}
// FIXME: proc-macro diagnostics
- fn collect(&mut self, tree_id: TreeId, assoc_items: &[AssocItem]) {
- let item_tree = tree_id.item_tree(self.db);
+ fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) {
+ let container = self.container;
+ self.items.reserve(assoc_items.len());
'items: for &item in assoc_items {
let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
@@ -509,9 +502,9 @@ impl<'a> AssocItemCollector<'a> {
continue 'attrs;
}
}
- match self.expander.enter_expand_id(self.db, call_id) {
- ExpandResult { value: Some((mark, mac)), .. } => {
- self.collect_macro_items(mark, mac);
+ match self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id) {
+ ExpandResult { value: Some((mark, _)), .. } => {
+ self.collect_macro_items(mark);
continue 'items;
}
ExpandResult { .. } => {}
@@ -522,44 +515,43 @@ impl<'a> AssocItemCollector<'a> {
match item {
AssocItem::Function(id) => {
let item = &item_tree[id];
+
let def =
- FunctionLoc { container: self.container, id: ItemTreeId::new(tree_id, id) }
- .intern(self.db);
+ FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
self.items.push((item.name.clone(), def.into()));
}
AssocItem::Const(id) => {
let item = &item_tree[id];
+
let name = match item.name.clone() {
Some(name) => name,
None => continue,
};
let def =
- ConstLoc { container: self.container, id: ItemTreeId::new(tree_id, id) }
- .intern(self.db);
+ ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
self.items.push((name, def.into()));
}
AssocItem::TypeAlias(id) => {
let item = &item_tree[id];
- let def = TypeAliasLoc {
- container: self.container,
- id: ItemTreeId::new(tree_id, id),
- }
- .intern(self.db);
+
+ let def = TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }
+ .intern(self.db);
self.items.push((item.name.clone(), def.into()));
}
AssocItem::MacroCall(call) => {
- let call = &item_tree[call];
- let ast_id_map = self.db.ast_id_map(self.expander.current_file_id());
if let Some(root) = self.db.parse_or_expand(self.expander.current_file_id()) {
+ let call = &item_tree[call];
+
+ let ast_id_map = self.db.ast_id_map(self.expander.current_file_id());
let call = ast_id_map.get(call.ast_id).to_node(&root);
let _cx = stdx::panic_context::enter(format!(
"collect_items MacroCall: {}",
call
));
- let res = self.expander.enter_expand(self.db, call);
+ let res = self.expander.enter_expand::<ast::MacroItems>(self.db, call);
- if let Ok(ExpandResult { value: Some((mark, mac)), .. }) = res {
- self.collect_macro_items(mark, mac);
+ if let Ok(ExpandResult { value: Some((mark, _)), .. }) = res {
+ self.collect_macro_items(mark);
}
}
}
@@ -567,14 +559,13 @@ impl<'a> AssocItemCollector<'a> {
}
}
- fn collect_macro_items(&mut self, mark: Mark, mac: ast::MacroItems) {
- let src: InFile<ast::MacroItems> = self.expander.to_source(mac);
- let tree_id = item_tree::TreeId::new(src.file_id, None);
+ fn collect_macro_items(&mut self, mark: Mark) {
+ let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
let item_tree = tree_id.item_tree(self.db);
- let iter: Vec<_> =
+ let iter: SmallVec<[_; 2]> =
item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item).collect();
- self.collect(tree_id, &iter);
+ self.collect(&item_tree, tree_id, &iter);
self.expander.exit(self.db, mark);
}
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index a32513cf65..c67046dfda 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -70,7 +70,7 @@ use syntax::{ast, SmolStr};
use crate::{
db::DefDatabase,
item_scope::{BuiltinShadowMode, ItemScope},
- item_tree::TreeId,
+ item_tree::{ItemTreeId, Mod, TreeId},
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
path::ModPath,
per_ns::PerNs,
@@ -141,9 +141,11 @@ pub enum ModuleOrigin {
File {
is_mod_rs: bool,
declaration: AstId<ast::Module>,
+ declaration_tree_id: ItemTreeId<Mod>,
definition: FileId,
},
Inline {
+ definition_tree_id: ItemTreeId<Mod>,
definition: AstId<ast::Module>,
},
/// Pseudo-module introduced by a block scope (contains only inner items).
@@ -186,7 +188,7 @@ impl ModuleOrigin {
let sf = db.parse(file_id).tree();
InFile::new(file_id.into(), ModuleSource::SourceFile(sf))
}
- ModuleOrigin::Inline { definition } => InFile::new(
+ ModuleOrigin::Inline { definition, .. } => InFile::new(
definition.file_id,
ModuleSource::Module(definition.to_node(db.upcast())),
),
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 5f40d26a2e..67651e0641 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1525,7 +1525,7 @@ impl ModCollector<'_, '_> {
};
match item {
- ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
+ ModItem::Mod(m) => self.collect_module(m, &attrs),
ModItem::Import(import_id) => {
let imports = Import::from_use(
db,
@@ -1700,9 +1700,10 @@ impl ModCollector<'_, '_> {
}
}
- fn collect_module(&mut self, module: &Mod, attrs: &Attrs) {
+ fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
let path_attr = attrs.by_key("path").string_value();
let is_macro_use = attrs.by_key("macro_use").exists();
+ let module = &self.item_tree[module_id];
match &module.kind {
// inline module, just recurse
ModKind::Inline { items } => {
@@ -1711,6 +1712,7 @@ impl ModCollector<'_, '_> {
AstId::new(self.file_id(), module.ast_id),
None,
&self.item_tree[module.visibility],
+ module_id,
);
if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
@@ -1748,6 +1750,7 @@ impl ModCollector<'_, '_> {
ast_id,
Some((file_id, is_mod_rs)),
&self.item_tree[module.visibility],
+ module_id,
);
ModCollector {
def_collector: self.def_collector,
@@ -1774,6 +1777,7 @@ impl ModCollector<'_, '_> {
ast_id,
None,
&self.item_tree[module.visibility],
+ module_id,
);
self.def_collector.def_map.diagnostics.push(
DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
@@ -1790,6 +1794,7 @@ impl ModCollector<'_, '_> {
declaration: AstId<ast::Module>,
definition: Option<(FileId, bool)>,
visibility: &crate::visibility::RawVisibility,
+ mod_tree_id: FileItemTreeId<Mod>,
) -> LocalModuleId {
let def_map = &mut self.def_collector.def_map;
let vis = def_map
@@ -1797,10 +1802,16 @@ impl ModCollector<'_, '_> {
.unwrap_or(Visibility::Public);
let modules = &mut def_map.modules;
let origin = match definition {
- None => ModuleOrigin::Inline { definition: declaration },
- Some((definition, is_mod_rs)) => {
- ModuleOrigin::File { declaration, definition, is_mod_rs }
- }
+ None => ModuleOrigin::Inline {
+ definition: declaration,
+ definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
+ },
+ Some((definition, is_mod_rs)) => ModuleOrigin::File {
+ declaration,
+ definition,
+ is_mod_rs,
+ declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
+ },
};
let res = modules.alloc(ModuleData::new(origin, vis));