From 8da50c907754d9af1dc4532938d7d72f34ec96bf Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 5 Mar 2021 14:06:09 +0100 Subject: Change `ChildBySource` to allow reusing `DynMap` --- crates/hir_def/src/child_by_source.rs | 46 +++++++++++++---------------------- crates/hir_def/src/generics.rs | 4 +-- 2 files changed, 18 insertions(+), 32 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 75c2d756b..6dde74138 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs @@ -17,13 +17,16 @@ use crate::{ }; pub trait ChildBySource { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap; -} - -impl ChildBySource for TraitId { fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { let mut res = DynMap::default(); + self.child_by_source_to(db, &mut res); + res + } + fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap); +} +impl ChildBySource for TraitId { + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let data = db.trait_data(*self); for (_name, item) in data.items.iter() { match *item { @@ -41,15 +44,11 @@ impl ChildBySource for TraitId { } } } - - res } } impl ChildBySource for ImplId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { - let mut res = DynMap::default(); - + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let data = db.impl_data(*self); for &item in data.items.iter() { match item { @@ -67,25 +66,21 @@ impl ChildBySource for ImplId { } } } - - res } } impl ChildBySource for ModuleId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let def_map = self.def_map(db); let module_data = &def_map[self.local_id]; - module_data.scope.child_by_source(db) + module_data.scope.child_by_source_to(db, res); } } impl ChildBySource for ItemScope { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { - let mut res = DynMap::default(); - self.declarations().for_each(|item| add_module_def(db, &mut res, item)); - self.impls().for_each(|imp| add_impl(db, &mut res, imp)); - return res; + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { + self.declarations().for_each(|item| add_module_def(db, res, item)); + self.impls().for_each(|imp| add_impl(db, res, imp)); fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { match item { @@ -134,9 +129,7 @@ impl ChildBySource for ItemScope { } impl ChildBySource for VariantId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { - let mut res = DynMap::default(); - + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let arena_map = self.child_source(db); let arena_map = arena_map.as_ref(); for (local_id, source) in arena_map.value.iter() { @@ -150,28 +143,23 @@ impl ChildBySource for VariantId { } } } - res } } impl ChildBySource for EnumId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { - let mut res = DynMap::default(); - + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let arena_map = self.child_source(db); let arena_map = arena_map.as_ref(); for (local_id, source) in arena_map.value.iter() { let id = EnumVariantId { parent: *self, local_id }; res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) } - - res } } impl ChildBySource for DefWithBodyId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let body = db.body(*self); - body.item_scope.child_by_source(db) + body.item_scope.child_by_source_to(db, res); } } diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 3ace3be1f..a056ab797 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -421,8 +421,7 @@ impl HasChildSource for GenericDefId { } impl ChildBySource for GenericDefId { - fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { - let mut res = DynMap::default(); + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let (_, sm) = GenericParams::new(db, *self); let sm = sm.as_ref(); @@ -440,6 +439,5 @@ impl ChildBySource for GenericDefId { let id = ConstParamId { parent: *self, local_id }; res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); } - res } } -- cgit v1.2.3 From 13f4356d2f05c79a01e55b1bdd91d9a2dcf9c6f2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 5 Mar 2021 14:08:23 +0100 Subject: Store inner `BlockId`s in `Body` --- crates/hir_def/src/body.rs | 4 +++- crates/hir_def/src/body/lower.rs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index b1a3fe1cb..9dbe717e5 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs @@ -32,7 +32,7 @@ use crate::{ nameres::DefMap, path::{ModPath, Path}, src::HasSource, - AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, + AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, }; /// A subset of Expander that only deals with cfg attributes. We only need it to @@ -226,6 +226,8 @@ pub struct Body { pub params: Vec, /// The `ExprId` of the actual body expression. pub body_expr: ExprId, + /// Block expressions in this body that may contain inner items. + pub block_scopes: Vec, pub item_scope: ItemScope, _c: Count, } diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index d4abe819d..c3aa1dc37 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -76,6 +76,7 @@ pub(super) fn lower( labels: Arena::default(), params: Vec::new(), body_expr: dummy_expr_id(), + block_scopes: Vec::new(), item_scope: Default::default(), _c: Count::new(), }, @@ -700,6 +701,8 @@ impl ExprCollector<'_> { let block_loc = BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; let block_id = self.db.intern_block(block_loc); + self.body.block_scopes.push(block_id); + let opt_def_map = self.db.block_def_map(block_id); let has_def_map = opt_def_map.is_some(); let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); -- cgit v1.2.3 From c12f7be8d33f9ddfd69f72fb75acc5b12d149527 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 5 Mar 2021 14:08:36 +0100 Subject: Use `body.block_scopes` in `ChildBySource` --- crates/hir_def/src/child_by_source.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 6dde74138..2a331dcaf 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs @@ -160,6 +160,10 @@ impl ChildBySource for EnumId { impl ChildBySource for DefWithBodyId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { let body = db.body(*self); - body.item_scope.child_by_source_to(db, res); + for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { + // All block expressions are merged into the same map, because they logically all add + // inner items to the containing `DefWithBodyId`. + def_map[def_map.root()].scope.child_by_source_to(db, res); + } } } -- cgit v1.2.3 From 6be4f30cae93479c19dfe313ab13b8ffd3f7a27f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 5 Mar 2021 14:53:54 +0100 Subject: Remove `item_scope` field from `Body` --- crates/hir_def/src/body.rs | 7 +- crates/hir_def/src/body/lower.rs | 143 ++------------------------------------- crates/hir_def/src/item_scope.rs | 31 --------- 3 files changed, 6 insertions(+), 175 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 9dbe717e5..19c4eb521 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs @@ -28,7 +28,6 @@ use crate::{ db::DefDatabase, expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, item_scope::BuiltinShadowMode, - item_scope::ItemScope, nameres::DefMap, path::{ModPath, Path}, src::HasSource, @@ -228,7 +227,6 @@ pub struct Body { pub body_expr: ExprId, /// Block expressions in this body that may contain inner items. pub block_scopes: Vec, - pub item_scope: ItemScope, _c: Count, } @@ -297,7 +295,7 @@ impl Body { } }; let expander = Expander::new(db, file_id, module); - let (body, source_map) = Body::new(db, def, expander, params, body); + let (body, source_map) = Body::new(db, expander, params, body); (Arc::new(body), Arc::new(source_map)) } @@ -307,12 +305,11 @@ impl Body { fn new( db: &dyn DefDatabase, - def: DefWithBodyId, expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { - lower::lower(db, def, expander, params, body) + lower::lower(db, expander, params, body) } } diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index c3aa1dc37..4d79ab72c 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -1,13 +1,13 @@ //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` //! representation. -use std::{any::type_name, mem, sync::Arc}; +use std::{mem, sync::Arc}; use either::Either; use hir_expand::{ hygiene::Hygiene, name::{name, AsName, Name}, - ExpandError, HirFileId, MacroDefId, MacroDefKind, + ExpandError, HirFileId, }; use la_arena::Arena; use profile::Count; @@ -32,11 +32,10 @@ use crate::{ Statement, }, item_scope::BuiltinShadowMode, - item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, + item_tree::ItemTree, path::{GenericArgs, Path}, type_ref::{Mutability, Rawness, TypeRef}, - AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, - ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, + AdtId, BlockLoc, ModuleDefId, }; use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; @@ -60,7 +59,6 @@ impl LowerCtx { pub(super) fn lower( db: &dyn DefDatabase, - def: DefWithBodyId, expander: Expander, params: Option, body: Option, @@ -68,7 +66,6 @@ pub(super) fn lower( let item_tree = db.item_tree(expander.current_file_id); ExprCollector { db, - def, source_map: BodySourceMap::default(), body: Body { exprs: Arena::default(), @@ -77,7 +74,6 @@ pub(super) fn lower( params: Vec::new(), body_expr: dummy_expr_id(), block_scopes: Vec::new(), - item_scope: Default::default(), _c: Count::new(), }, item_trees: { @@ -92,7 +88,6 @@ pub(super) fn lower( struct ExprCollector<'a> { db: &'a dyn DefDatabase, - def: DefWithBodyId, expander: Expander, body: Body, source_map: BodySourceMap, @@ -606,32 +601,6 @@ impl ExprCollector<'_> { } } - fn find_inner_item(&self, ast: &N::Source) -> Option> { - let id = self.expander.ast_id(ast); - let tree = &self.item_trees[&id.file_id]; - - // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes - - // Root file (non-macro). - let item_tree_id = tree - .all_inner_items() - .chain(tree.top_level_items().iter().copied()) - .filter_map(|mod_item| mod_item.downcast::()) - .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast()) - .or_else(|| { - log::debug!( - "couldn't find inner {} item for {:?} (AST: `{}` - {:?})", - type_name::(), - id, - ast.syntax(), - ast.syntax(), - ); - None - })?; - - Some(ItemTreeId::new(id.file_id, item_tree_id)) - } - fn collect_expr_opt(&mut self, expr: Option) -> ExprId { if let Some(expr) = expr { self.collect_expr(expr) @@ -663,7 +632,6 @@ impl ExprCollector<'_> { match expansion { Some(expansion) => { let statements: ast::MacroStmts = expansion; - this.collect_stmts_items(statements.statements()); statements.statements().for_each(|stmt| { if let Some(mut r) = this.collect_stmt(stmt) { @@ -710,7 +678,6 @@ impl ExprCollector<'_> { let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); let prev_local_module = mem::replace(&mut self.expander.module, module); - self.collect_stmts_items(block.statements()); let statements = block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); let tail = block.tail_expr().map(|e| self.collect_expr(e)); @@ -725,108 +692,6 @@ impl ExprCollector<'_> { expr_id } - fn collect_stmts_items(&mut self, stmts: ast::AstChildren) { - let container = ContainerId::DefWithBodyId(self.def); - - let items = stmts - .filter_map(|stmt| match stmt { - ast::Stmt::Item(it) => Some(it), - ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None, - }) - .filter_map(|item| { - let (def, name): (ModuleDefId, Option) = match item { - ast::Item::Fn(def) => { - let id = self.find_inner_item(&def)?; - ( - FunctionLoc { container: container.into(), id }.intern(self.db).into(), - def.name(), - ) - } - ast::Item::TypeAlias(def) => { - let id = self.find_inner_item(&def)?; - ( - TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), - def.name(), - ) - } - ast::Item::Const(def) => { - let id = self.find_inner_item(&def)?; - ( - ConstLoc { container: container.into(), id }.intern(self.db).into(), - def.name(), - ) - } - ast::Item::Static(def) => { - let id = self.find_inner_item(&def)?; - (StaticLoc { container, id }.intern(self.db).into(), def.name()) - } - ast::Item::Struct(def) => { - let id = self.find_inner_item(&def)?; - (StructLoc { container, id }.intern(self.db).into(), def.name()) - } - ast::Item::Enum(def) => { - let id = self.find_inner_item(&def)?; - (EnumLoc { container, id }.intern(self.db).into(), def.name()) - } - ast::Item::Union(def) => { - let id = self.find_inner_item(&def)?; - (UnionLoc { container, id }.intern(self.db).into(), def.name()) - } - ast::Item::Trait(def) => { - let id = self.find_inner_item(&def)?; - (TraitLoc { container, id }.intern(self.db).into(), def.name()) - } - ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks - ast::Item::Impl(_) - | ast::Item::Use(_) - | ast::Item::ExternCrate(_) - | ast::Item::Module(_) - | ast::Item::MacroCall(_) => return None, - ast::Item::MacroRules(def) => { - return Some(Either::Right(ast::Macro::from(def))); - } - ast::Item::MacroDef(def) => { - return Some(Either::Right(ast::Macro::from(def))); - } - }; - - Some(Either::Left((def, name))) - }) - .collect::>(); - - for either in items { - match either { - Either::Left((def, name)) => { - self.body.item_scope.define_def(def); - if let Some(name) = name { - let vis = crate::visibility::Visibility::Public; // FIXME determine correctly - let has_constructor = match def { - ModuleDefId::AdtId(AdtId::StructId(s)) => { - self.db.struct_data(s).variant_data.kind() != StructKind::Record - } - _ => true, - }; - self.body.item_scope.push_res( - name.as_name(), - crate::per_ns::PerNs::from_def(def, vis, has_constructor), - ); - } - } - Either::Right(e) => { - let mac = MacroDefId { - krate: self.expander.def_map.krate(), - ast_id: Some(self.expander.ast_id(&e)), - kind: MacroDefKind::Declarative, - local_inner: false, - }; - if let Some(name) = e.name() { - self.body.item_scope.define_legacy_macro(name.as_name(), mac); - } - } - } - } - } - fn collect_block_opt(&mut self, expr: Option) -> ExprId { if let Some(block) = expr { self.collect_block(block) diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 919933813..aafd73b60 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs @@ -168,37 +168,6 @@ impl ItemScope { self.unnamed_trait_imports.insert(tr, vis); } - pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { - let mut changed = false; - - if let Some(types) = def.types { - self.types.entry(name.clone()).or_insert_with(|| { - changed = true; - types - }); - } - if let Some(values) = def.values { - self.values.entry(name.clone()).or_insert_with(|| { - changed = true; - values - }); - } - if let Some(macros) = def.macros { - self.macros.entry(name.clone()).or_insert_with(|| { - changed = true; - macros - }); - } - - if def.is_none() { - if self.unresolved.insert(name) { - changed = true; - } - } - - changed - } - pub(crate) fn push_res_with_import( &mut self, glob_imports: &mut PerNsGlobImports, -- cgit v1.2.3 From 12f6bdcfd9fe1393887b3be0d0329fcf11492e75 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 9 Mar 2021 18:18:35 +0100 Subject: Check ancestor maps when computing traits in scope --- crates/hir_def/src/resolver.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 77ff21739..28b184f7c 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -342,6 +342,16 @@ impl Resolver { traits.extend(prelude_def_map[prelude.local_id].scope.traits()); } traits.extend(m.def_map[m.module_id].scope.traits()); + + // Add all traits that are in scope because of the containing DefMaps + m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { + if let Some(prelude) = def_map.prelude() { + let prelude_def_map = prelude.def_map(db); + traits.extend(prelude_def_map[prelude.local_id].scope.traits()); + } + traits.extend(def_map[module].scope.traits()); + None::<()> + }); } } traits -- cgit v1.2.3 From a430549aa6cb78e3a6c9258305b348743c4d7449 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 9 Mar 2021 18:27:16 +0100 Subject: Stop using `ContainerId` in `AssocContainerId` --- crates/hir_def/src/lib.rs | 6 +++--- crates/hir_def/src/nameres/collector.rs | 6 +++--- crates/hir_def/src/resolver.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 4498d94bb..ab3b17f6c 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -286,11 +286,11 @@ pub enum ContainerId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum AssocContainerId { - ContainerId(ContainerId), + ModuleId(ModuleId), ImplId(ImplId), TraitId(TraitId), } -impl_from!(ContainerId for AssocContainerId); +impl_from!(ModuleId for AssocContainerId); /// A Data Type #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -459,7 +459,7 @@ impl HasModule for ContainerId { impl HasModule for AssocContainerId { fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { match *self { - AssocContainerId::ContainerId(it) => it.module(db), + AssocContainerId::ModuleId(it) => it, AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), } diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 3bb69d935..5bf2ba721 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -1121,7 +1121,7 @@ impl ModCollector<'_, '_> { def = Some(DefData { id: FunctionLoc { - container: container.into(), + container: module.into(), id: ItemTreeId::new(self.file_id, id), } .intern(self.def_collector.db) @@ -1188,7 +1188,7 @@ impl ModCollector<'_, '_> { if let Some(name) = &it.name { def = Some(DefData { id: ConstLoc { - container: container.into(), + container: module.into(), id: ItemTreeId::new(self.file_id, id), } .intern(self.def_collector.db) @@ -1228,7 +1228,7 @@ impl ModCollector<'_, '_> { def = Some(DefData { id: TypeAliasLoc { - container: container.into(), + container: module.into(), id: ItemTreeId::new(self.file_id, id), } .intern(self.def_collector.db) diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 28b184f7c..6f036c8c4 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -700,7 +700,7 @@ impl HasResolver for ContainerId { impl HasResolver for AssocContainerId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { match self { - AssocContainerId::ContainerId(it) => it.resolver(db), + AssocContainerId::ModuleId(it) => it.resolver(db), AssocContainerId::TraitId(it) => it.resolver(db), AssocContainerId::ImplId(it) => it.resolver(db), } -- cgit v1.2.3