aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/hir_def/src/body.rs11
-rw-r--r--crates/hir_def/src/body/lower.rs146
-rw-r--r--crates/hir_def/src/child_by_source.rs50
-rw-r--r--crates/hir_def/src/generics.rs4
-rw-r--r--crates/hir_def/src/item_scope.rs31
-rw-r--r--crates/hir_def/src/lib.rs6
-rw-r--r--crates/hir_def/src/nameres/collector.rs6
-rw-r--r--crates/hir_def/src/resolver.rs12
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs11
-rw-r--r--crates/hir_ty/src/infer/path.rs2
-rw-r--r--crates/hir_ty/src/method_resolution.rs2
-rw-r--r--crates/hir_ty/src/tests.rs20
-rw-r--r--crates/hir_ty/src/tests/traits.rs33
-rw-r--r--crates/hir_ty/src/utils.rs2
15 files changed, 111 insertions, 229 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 638398e29..c6d424c48 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1157,7 +1157,7 @@ where
1157{ 1157{
1158 match id.lookup(db.upcast()).container { 1158 match id.lookup(db.upcast()).container {
1159 AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), 1159 AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
1160 AssocContainerId::ContainerId(_) => None, 1160 AssocContainerId::ModuleId(_) => None,
1161 } 1161 }
1162} 1162}
1163 1163
@@ -1185,7 +1185,7 @@ impl AssocItem {
1185 match container { 1185 match container {
1186 AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), 1186 AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
1187 AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()), 1187 AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
1188 AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), 1188 AssocContainerId::ModuleId(_) => panic!("invalid AssocItem"),
1189 } 1189 }
1190 } 1190 }
1191 1191
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index b1a3fe1cb..19c4eb521 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -28,11 +28,10 @@ use crate::{
28 db::DefDatabase, 28 db::DefDatabase,
29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, 29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
30 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
31 item_scope::ItemScope,
32 nameres::DefMap, 31 nameres::DefMap,
33 path::{ModPath, Path}, 32 path::{ModPath, Path},
34 src::HasSource, 33 src::HasSource,
35 AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, 34 AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId,
36}; 35};
37 36
38/// A subset of Expander that only deals with cfg attributes. We only need it to 37/// A subset of Expander that only deals with cfg attributes. We only need it to
@@ -226,7 +225,8 @@ pub struct Body {
226 pub params: Vec<PatId>, 225 pub params: Vec<PatId>,
227 /// The `ExprId` of the actual body expression. 226 /// The `ExprId` of the actual body expression.
228 pub body_expr: ExprId, 227 pub body_expr: ExprId,
229 pub item_scope: ItemScope, 228 /// Block expressions in this body that may contain inner items.
229 pub block_scopes: Vec<BlockId>,
230 _c: Count<Self>, 230 _c: Count<Self>,
231} 231}
232 232
@@ -295,7 +295,7 @@ impl Body {
295 } 295 }
296 }; 296 };
297 let expander = Expander::new(db, file_id, module); 297 let expander = Expander::new(db, file_id, module);
298 let (body, source_map) = Body::new(db, def, expander, params, body); 298 let (body, source_map) = Body::new(db, expander, params, body);
299 (Arc::new(body), Arc::new(source_map)) 299 (Arc::new(body), Arc::new(source_map))
300 } 300 }
301 301
@@ -305,12 +305,11 @@ impl Body {
305 305
306 fn new( 306 fn new(
307 db: &dyn DefDatabase, 307 db: &dyn DefDatabase,
308 def: DefWithBodyId,
309 expander: Expander, 308 expander: Expander,
310 params: Option<ast::ParamList>, 309 params: Option<ast::ParamList>,
311 body: Option<ast::Expr>, 310 body: Option<ast::Expr>,
312 ) -> (Body, BodySourceMap) { 311 ) -> (Body, BodySourceMap) {
313 lower::lower(db, def, expander, params, body) 312 lower::lower(db, expander, params, body)
314 } 313 }
315} 314}
316 315
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index d4abe819d..4d79ab72c 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -1,13 +1,13 @@
1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation. 2//! representation.
3 3
4use std::{any::type_name, mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use either::Either; 6use either::Either;
7use hir_expand::{ 7use hir_expand::{
8 hygiene::Hygiene, 8 hygiene::Hygiene,
9 name::{name, AsName, Name}, 9 name::{name, AsName, Name},
10 ExpandError, HirFileId, MacroDefId, MacroDefKind, 10 ExpandError, HirFileId,
11}; 11};
12use la_arena::Arena; 12use la_arena::Arena;
13use profile::Count; 13use profile::Count;
@@ -32,11 +32,10 @@ use crate::{
32 Statement, 32 Statement,
33 }, 33 },
34 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
35 item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, 35 item_tree::ItemTree,
36 path::{GenericArgs, Path}, 36 path::{GenericArgs, Path},
37 type_ref::{Mutability, Rawness, TypeRef}, 37 type_ref::{Mutability, Rawness, TypeRef},
38 AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, 38 AdtId, BlockLoc, ModuleDefId,
39 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
40}; 39};
41 40
42use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; 41use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
@@ -60,7 +59,6 @@ impl LowerCtx {
60 59
61pub(super) fn lower( 60pub(super) fn lower(
62 db: &dyn DefDatabase, 61 db: &dyn DefDatabase,
63 def: DefWithBodyId,
64 expander: Expander, 62 expander: Expander,
65 params: Option<ast::ParamList>, 63 params: Option<ast::ParamList>,
66 body: Option<ast::Expr>, 64 body: Option<ast::Expr>,
@@ -68,7 +66,6 @@ pub(super) fn lower(
68 let item_tree = db.item_tree(expander.current_file_id); 66 let item_tree = db.item_tree(expander.current_file_id);
69 ExprCollector { 67 ExprCollector {
70 db, 68 db,
71 def,
72 source_map: BodySourceMap::default(), 69 source_map: BodySourceMap::default(),
73 body: Body { 70 body: Body {
74 exprs: Arena::default(), 71 exprs: Arena::default(),
@@ -76,7 +73,7 @@ pub(super) fn lower(
76 labels: Arena::default(), 73 labels: Arena::default(),
77 params: Vec::new(), 74 params: Vec::new(),
78 body_expr: dummy_expr_id(), 75 body_expr: dummy_expr_id(),
79 item_scope: Default::default(), 76 block_scopes: Vec::new(),
80 _c: Count::new(), 77 _c: Count::new(),
81 }, 78 },
82 item_trees: { 79 item_trees: {
@@ -91,7 +88,6 @@ pub(super) fn lower(
91 88
92struct ExprCollector<'a> { 89struct ExprCollector<'a> {
93 db: &'a dyn DefDatabase, 90 db: &'a dyn DefDatabase,
94 def: DefWithBodyId,
95 expander: Expander, 91 expander: Expander,
96 body: Body, 92 body: Body,
97 source_map: BodySourceMap, 93 source_map: BodySourceMap,
@@ -605,32 +601,6 @@ impl ExprCollector<'_> {
605 } 601 }
606 } 602 }
607 603
608 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
609 let id = self.expander.ast_id(ast);
610 let tree = &self.item_trees[&id.file_id];
611
612 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
613
614 // Root file (non-macro).
615 let item_tree_id = tree
616 .all_inner_items()
617 .chain(tree.top_level_items().iter().copied())
618 .filter_map(|mod_item| mod_item.downcast::<N>())
619 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
620 .or_else(|| {
621 log::debug!(
622 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
623 type_name::<N>(),
624 id,
625 ast.syntax(),
626 ast.syntax(),
627 );
628 None
629 })?;
630
631 Some(ItemTreeId::new(id.file_id, item_tree_id))
632 }
633
634 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 604 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
635 if let Some(expr) = expr { 605 if let Some(expr) = expr {
636 self.collect_expr(expr) 606 self.collect_expr(expr)
@@ -662,7 +632,6 @@ impl ExprCollector<'_> {
662 match expansion { 632 match expansion {
663 Some(expansion) => { 633 Some(expansion) => {
664 let statements: ast::MacroStmts = expansion; 634 let statements: ast::MacroStmts = expansion;
665 this.collect_stmts_items(statements.statements());
666 635
667 statements.statements().for_each(|stmt| { 636 statements.statements().for_each(|stmt| {
668 if let Some(mut r) = this.collect_stmt(stmt) { 637 if let Some(mut r) = this.collect_stmt(stmt) {
@@ -700,6 +669,8 @@ impl ExprCollector<'_> {
700 let block_loc = 669 let block_loc =
701 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 670 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
702 let block_id = self.db.intern_block(block_loc); 671 let block_id = self.db.intern_block(block_loc);
672 self.body.block_scopes.push(block_id);
673
703 let opt_def_map = self.db.block_def_map(block_id); 674 let opt_def_map = self.db.block_def_map(block_id);
704 let has_def_map = opt_def_map.is_some(); 675 let has_def_map = opt_def_map.is_some();
705 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 676 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
@@ -707,7 +678,6 @@ impl ExprCollector<'_> {
707 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 678 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
708 let prev_local_module = mem::replace(&mut self.expander.module, module); 679 let prev_local_module = mem::replace(&mut self.expander.module, module);
709 680
710 self.collect_stmts_items(block.statements());
711 let statements = 681 let statements =
712 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); 682 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
713 let tail = block.tail_expr().map(|e| self.collect_expr(e)); 683 let tail = block.tail_expr().map(|e| self.collect_expr(e));
@@ -722,108 +692,6 @@ impl ExprCollector<'_> {
722 expr_id 692 expr_id
723 } 693 }
724 694
725 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
726 let container = ContainerId::DefWithBodyId(self.def);
727
728 let items = stmts
729 .filter_map(|stmt| match stmt {
730 ast::Stmt::Item(it) => Some(it),
731 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
732 })
733 .filter_map(|item| {
734 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
735 ast::Item::Fn(def) => {
736 let id = self.find_inner_item(&def)?;
737 (
738 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
739 def.name(),
740 )
741 }
742 ast::Item::TypeAlias(def) => {
743 let id = self.find_inner_item(&def)?;
744 (
745 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
746 def.name(),
747 )
748 }
749 ast::Item::Const(def) => {
750 let id = self.find_inner_item(&def)?;
751 (
752 ConstLoc { container: container.into(), id }.intern(self.db).into(),
753 def.name(),
754 )
755 }
756 ast::Item::Static(def) => {
757 let id = self.find_inner_item(&def)?;
758 (StaticLoc { container, id }.intern(self.db).into(), def.name())
759 }
760 ast::Item::Struct(def) => {
761 let id = self.find_inner_item(&def)?;
762 (StructLoc { container, id }.intern(self.db).into(), def.name())
763 }
764 ast::Item::Enum(def) => {
765 let id = self.find_inner_item(&def)?;
766 (EnumLoc { container, id }.intern(self.db).into(), def.name())
767 }
768 ast::Item::Union(def) => {
769 let id = self.find_inner_item(&def)?;
770 (UnionLoc { container, id }.intern(self.db).into(), def.name())
771 }
772 ast::Item::Trait(def) => {
773 let id = self.find_inner_item(&def)?;
774 (TraitLoc { container, id }.intern(self.db).into(), def.name())
775 }
776 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
777 ast::Item::Impl(_)
778 | ast::Item::Use(_)
779 | ast::Item::ExternCrate(_)
780 | ast::Item::Module(_)
781 | ast::Item::MacroCall(_) => return None,
782 ast::Item::MacroRules(def) => {
783 return Some(Either::Right(ast::Macro::from(def)));
784 }
785 ast::Item::MacroDef(def) => {
786 return Some(Either::Right(ast::Macro::from(def)));
787 }
788 };
789
790 Some(Either::Left((def, name)))
791 })
792 .collect::<Vec<_>>();
793
794 for either in items {
795 match either {
796 Either::Left((def, name)) => {
797 self.body.item_scope.define_def(def);
798 if let Some(name) = name {
799 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
800 let has_constructor = match def {
801 ModuleDefId::AdtId(AdtId::StructId(s)) => {
802 self.db.struct_data(s).variant_data.kind() != StructKind::Record
803 }
804 _ => true,
805 };
806 self.body.item_scope.push_res(
807 name.as_name(),
808 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
809 );
810 }
811 }
812 Either::Right(e) => {
813 let mac = MacroDefId {
814 krate: self.expander.def_map.krate(),
815 ast_id: Some(self.expander.ast_id(&e)),
816 kind: MacroDefKind::Declarative,
817 local_inner: false,
818 };
819 if let Some(name) = e.name() {
820 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
821 }
822 }
823 }
824 }
825 }
826
827 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 695 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
828 if let Some(block) = expr { 696 if let Some(block) = expr {
829 self.collect_block(block) 697 self.collect_block(block)
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index 75c2d756b..2a331dcaf 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::{
17}; 17};
18 18
19pub trait ChildBySource { 19pub trait ChildBySource {
20 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap;
21}
22
23impl ChildBySource for TraitId {
24 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 20 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
25 let mut res = DynMap::default(); 21 let mut res = DynMap::default();
22 self.child_by_source_to(db, &mut res);
23 res
24 }
25 fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap);
26}
26 27
28impl ChildBySource for TraitId {
29 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
27 let data = db.trait_data(*self); 30 let data = db.trait_data(*self);
28 for (_name, item) in data.items.iter() { 31 for (_name, item) in data.items.iter() {
29 match *item { 32 match *item {
@@ -41,15 +44,11 @@ impl ChildBySource for TraitId {
41 } 44 }
42 } 45 }
43 } 46 }
44
45 res
46 } 47 }
47} 48}
48 49
49impl ChildBySource for ImplId { 50impl ChildBySource for ImplId {
50 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 51 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
51 let mut res = DynMap::default();
52
53 let data = db.impl_data(*self); 52 let data = db.impl_data(*self);
54 for &item in data.items.iter() { 53 for &item in data.items.iter() {
55 match item { 54 match item {
@@ -67,25 +66,21 @@ impl ChildBySource for ImplId {
67 } 66 }
68 } 67 }
69 } 68 }
70
71 res
72 } 69 }
73} 70}
74 71
75impl ChildBySource for ModuleId { 72impl ChildBySource for ModuleId {
76 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 73 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
77 let def_map = self.def_map(db); 74 let def_map = self.def_map(db);
78 let module_data = &def_map[self.local_id]; 75 let module_data = &def_map[self.local_id];
79 module_data.scope.child_by_source(db) 76 module_data.scope.child_by_source_to(db, res);
80 } 77 }
81} 78}
82 79
83impl ChildBySource for ItemScope { 80impl ChildBySource for ItemScope {
84 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
85 let mut res = DynMap::default(); 82 self.declarations().for_each(|item| add_module_def(db, res, item));
86 self.declarations().for_each(|item| add_module_def(db, &mut res, item)); 83 self.impls().for_each(|imp| add_impl(db, res, imp));
87 self.impls().for_each(|imp| add_impl(db, &mut res, imp));
88 return res;
89 84
90 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { 85 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
91 match item { 86 match item {
@@ -134,9 +129,7 @@ impl ChildBySource for ItemScope {
134} 129}
135 130
136impl ChildBySource for VariantId { 131impl ChildBySource for VariantId {
137 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 132 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
138 let mut res = DynMap::default();
139
140 let arena_map = self.child_source(db); 133 let arena_map = self.child_source(db);
141 let arena_map = arena_map.as_ref(); 134 let arena_map = arena_map.as_ref();
142 for (local_id, source) in arena_map.value.iter() { 135 for (local_id, source) in arena_map.value.iter() {
@@ -150,28 +143,27 @@ impl ChildBySource for VariantId {
150 } 143 }
151 } 144 }
152 } 145 }
153 res
154 } 146 }
155} 147}
156 148
157impl ChildBySource for EnumId { 149impl ChildBySource for EnumId {
158 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 150 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
159 let mut res = DynMap::default();
160
161 let arena_map = self.child_source(db); 151 let arena_map = self.child_source(db);
162 let arena_map = arena_map.as_ref(); 152 let arena_map = arena_map.as_ref();
163 for (local_id, source) in arena_map.value.iter() { 153 for (local_id, source) in arena_map.value.iter() {
164 let id = EnumVariantId { parent: *self, local_id }; 154 let id = EnumVariantId { parent: *self, local_id };
165 res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) 155 res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
166 } 156 }
167
168 res
169 } 157 }
170} 158}
171 159
172impl ChildBySource for DefWithBodyId { 160impl ChildBySource for DefWithBodyId {
173 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 161 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
174 let body = db.body(*self); 162 let body = db.body(*self);
175 body.item_scope.child_by_source(db) 163 for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
164 // All block expressions are merged into the same map, because they logically all add
165 // inner items to the containing `DefWithBodyId`.
166 def_map[def_map.root()].scope.child_by_source_to(db, res);
167 }
176 } 168 }
177} 169}
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<LocalConstParamId> for GenericDefId {
421} 421}
422 422
423impl ChildBySource for GenericDefId { 423impl ChildBySource for GenericDefId {
424 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 424 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
425 let mut res = DynMap::default();
426 let (_, sm) = GenericParams::new(db, *self); 425 let (_, sm) = GenericParams::new(db, *self);
427 426
428 let sm = sm.as_ref(); 427 let sm = sm.as_ref();
@@ -440,6 +439,5 @@ impl ChildBySource for GenericDefId {
440 let id = ConstParamId { parent: *self, local_id }; 439 let id = ConstParamId { parent: *self, local_id };
441 res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); 440 res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id);
442 } 441 }
443 res
444 } 442 }
445} 443}
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 {
168 self.unnamed_trait_imports.insert(tr, vis); 168 self.unnamed_trait_imports.insert(tr, vis);
169 } 169 }
170 170
171 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
172 let mut changed = false;
173
174 if let Some(types) = def.types {
175 self.types.entry(name.clone()).or_insert_with(|| {
176 changed = true;
177 types
178 });
179 }
180 if let Some(values) = def.values {
181 self.values.entry(name.clone()).or_insert_with(|| {
182 changed = true;
183 values
184 });
185 }
186 if let Some(macros) = def.macros {
187 self.macros.entry(name.clone()).or_insert_with(|| {
188 changed = true;
189 macros
190 });
191 }
192
193 if def.is_none() {
194 if self.unresolved.insert(name) {
195 changed = true;
196 }
197 }
198
199 changed
200 }
201
202 pub(crate) fn push_res_with_import( 171 pub(crate) fn push_res_with_import(
203 &mut self, 172 &mut self,
204 glob_imports: &mut PerNsGlobImports, 173 glob_imports: &mut PerNsGlobImports,
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 {
286 286
287#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 287#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
288pub enum AssocContainerId { 288pub enum AssocContainerId {
289 ContainerId(ContainerId), 289 ModuleId(ModuleId),
290 ImplId(ImplId), 290 ImplId(ImplId),
291 TraitId(TraitId), 291 TraitId(TraitId),
292} 292}
293impl_from!(ContainerId for AssocContainerId); 293impl_from!(ModuleId for AssocContainerId);
294 294
295/// A Data Type 295/// A Data Type
296#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 296#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -459,7 +459,7 @@ impl HasModule for ContainerId {
459impl HasModule for AssocContainerId { 459impl HasModule for AssocContainerId {
460 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 460 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
461 match *self { 461 match *self {
462 AssocContainerId::ContainerId(it) => it.module(db), 462 AssocContainerId::ModuleId(it) => it,
463 AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), 463 AssocContainerId::ImplId(it) => it.lookup(db).container.module(db),
464 AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), 464 AssocContainerId::TraitId(it) => it.lookup(db).container.module(db),
465 } 465 }
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<'_, '_> {
1121 1121
1122 def = Some(DefData { 1122 def = Some(DefData {
1123 id: FunctionLoc { 1123 id: FunctionLoc {
1124 container: container.into(), 1124 container: module.into(),
1125 id: ItemTreeId::new(self.file_id, id), 1125 id: ItemTreeId::new(self.file_id, id),
1126 } 1126 }
1127 .intern(self.def_collector.db) 1127 .intern(self.def_collector.db)
@@ -1188,7 +1188,7 @@ impl ModCollector<'_, '_> {
1188 if let Some(name) = &it.name { 1188 if let Some(name) = &it.name {
1189 def = Some(DefData { 1189 def = Some(DefData {
1190 id: ConstLoc { 1190 id: ConstLoc {
1191 container: container.into(), 1191 container: module.into(),
1192 id: ItemTreeId::new(self.file_id, id), 1192 id: ItemTreeId::new(self.file_id, id),
1193 } 1193 }
1194 .intern(self.def_collector.db) 1194 .intern(self.def_collector.db)
@@ -1228,7 +1228,7 @@ impl ModCollector<'_, '_> {
1228 1228
1229 def = Some(DefData { 1229 def = Some(DefData {
1230 id: TypeAliasLoc { 1230 id: TypeAliasLoc {
1231 container: container.into(), 1231 container: module.into(),
1232 id: ItemTreeId::new(self.file_id, id), 1232 id: ItemTreeId::new(self.file_id, id),
1233 } 1233 }
1234 .intern(self.def_collector.db) 1234 .intern(self.def_collector.db)
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 77ff21739..6f036c8c4 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -342,6 +342,16 @@ impl Resolver {
342 traits.extend(prelude_def_map[prelude.local_id].scope.traits()); 342 traits.extend(prelude_def_map[prelude.local_id].scope.traits());
343 } 343 }
344 traits.extend(m.def_map[m.module_id].scope.traits()); 344 traits.extend(m.def_map[m.module_id].scope.traits());
345
346 // Add all traits that are in scope because of the containing DefMaps
347 m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| {
348 if let Some(prelude) = def_map.prelude() {
349 let prelude_def_map = prelude.def_map(db);
350 traits.extend(prelude_def_map[prelude.local_id].scope.traits());
351 }
352 traits.extend(def_map[module].scope.traits());
353 None::<()>
354 });
345 } 355 }
346 } 356 }
347 traits 357 traits
@@ -690,7 +700,7 @@ impl HasResolver for ContainerId {
690impl HasResolver for AssocContainerId { 700impl HasResolver for AssocContainerId {
691 fn resolver(self, db: &dyn DefDatabase) -> Resolver { 701 fn resolver(self, db: &dyn DefDatabase) -> Resolver {
692 match self { 702 match self {
693 AssocContainerId::ContainerId(it) => it.resolver(db), 703 AssocContainerId::ModuleId(it) => it.resolver(db),
694 AssocContainerId::TraitId(it) => it.resolver(db), 704 AssocContainerId::TraitId(it) => it.resolver(db),
695 AssocContainerId::ImplId(it) => it.resolver(db), 705 AssocContainerId::ImplId(it) => it.resolver(db),
696 } 706 }
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index e230f9765..3605ca581 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -99,9 +99,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
99 let body = self.db.body(func.into()); 99 let body = self.db.body(func.into());
100 100
101 // Recursively validate inner scope items, such as static variables and constants. 101 // Recursively validate inner scope items, such as static variables and constants.
102 for (item_id, _) in body.item_scope.values() { 102 let db = self.db;
103 let mut validator = DeclValidator::new(self.db, self.krate, self.sink); 103 for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
104 validator.validate_item(item_id); 104 for (_, module) in block_def_map.modules() {
105 for (def_id, _) in module.scope.values() {
106 let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
107 validator.validate_item(def_id);
108 }
109 }
105 } 110 }
106 111
107 // Check whether non-snake case identifiers are allowed for this function. 112 // Check whether non-snake case identifiers are allowed for this function.
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 5d541104e..ae3554bac 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -260,7 +260,7 @@ impl<'a> InferenceContext<'a> {
260 })); 260 }));
261 Some(trait_substs) 261 Some(trait_substs)
262 } 262 }
263 AssocContainerId::ContainerId(_) => None, 263 AssocContainerId::ModuleId(_) => None,
264 }; 264 };
265 265
266 self.write_assoc_resolution(id, item); 266 self.write_assoc_resolution(id, item);
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 24db33c49..248367267 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -715,7 +715,7 @@ fn transform_receiver_ty(
715 .fill_with_unknown() 715 .fill_with_unknown()
716 .build() 716 .build()
717 } 717 }
718 AssocContainerId::ContainerId(_) => unreachable!(), 718 AssocContainerId::ModuleId(_) => unreachable!(),
719 }; 719 };
720 let sig = db.callable_item_signature(function_id.into()); 720 let sig = db.callable_item_signature(function_id.into());
721 Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) 721 Some(sig.value.params()[0].clone().subst_bound_vars(&substs))
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 7386a4e7b..fc770ea60 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -13,7 +13,7 @@ use std::{env, sync::Arc};
13use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; 13use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
14use expect_test::Expect; 14use expect_test::Expect;
15use hir_def::{ 15use hir_def::{
16 body::{BodySourceMap, SyntheticSyntax}, 16 body::{Body, BodySourceMap, SyntheticSyntax},
17 child_by_source::ChildBySource, 17 child_by_source::ChildBySource,
18 db::DefDatabase, 18 db::DefDatabase,
19 item_scope::ItemScope, 19 item_scope::ItemScope,
@@ -234,13 +234,13 @@ fn visit_module(
234 let def = it.into(); 234 let def = it.into();
235 cb(def); 235 cb(def);
236 let body = db.body(def); 236 let body = db.body(def);
237 visit_scope(db, crate_def_map, &body.item_scope, cb); 237 visit_body(db, &body, cb);
238 } 238 }
239 AssocItemId::ConstId(it) => { 239 AssocItemId::ConstId(it) => {
240 let def = it.into(); 240 let def = it.into();
241 cb(def); 241 cb(def);
242 let body = db.body(def); 242 let body = db.body(def);
243 visit_scope(db, crate_def_map, &body.item_scope, cb); 243 visit_body(db, &body, cb);
244 } 244 }
245 AssocItemId::TypeAliasId(_) => (), 245 AssocItemId::TypeAliasId(_) => (),
246 } 246 }
@@ -259,19 +259,19 @@ fn visit_module(
259 let def = it.into(); 259 let def = it.into();
260 cb(def); 260 cb(def);
261 let body = db.body(def); 261 let body = db.body(def);
262 visit_scope(db, crate_def_map, &body.item_scope, cb); 262 visit_body(db, &body, cb);
263 } 263 }
264 ModuleDefId::ConstId(it) => { 264 ModuleDefId::ConstId(it) => {
265 let def = it.into(); 265 let def = it.into();
266 cb(def); 266 cb(def);
267 let body = db.body(def); 267 let body = db.body(def);
268 visit_scope(db, crate_def_map, &body.item_scope, cb); 268 visit_body(db, &body, cb);
269 } 269 }
270 ModuleDefId::StaticId(it) => { 270 ModuleDefId::StaticId(it) => {
271 let def = it.into(); 271 let def = it.into();
272 cb(def); 272 cb(def);
273 let body = db.body(def); 273 let body = db.body(def);
274 visit_scope(db, crate_def_map, &body.item_scope, cb); 274 visit_body(db, &body, cb);
275 } 275 }
276 ModuleDefId::TraitId(it) => { 276 ModuleDefId::TraitId(it) => {
277 let trait_data = db.trait_data(it); 277 let trait_data = db.trait_data(it);
@@ -288,6 +288,14 @@ fn visit_module(
288 } 288 }
289 } 289 }
290 } 290 }
291
292 fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) {
293 for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
294 for (mod_id, _) in def_map.modules() {
295 visit_module(db, &def_map, mod_id, cb);
296 }
297 }
298 }
291} 299}
292 300
293fn ellipsize(mut text: String, max_len: usize) -> String { 301fn ellipsize(mut text: String, max_len: usize) -> String {
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 528092082..e185b1c0a 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3174,6 +3174,39 @@ fn f() {
3174} 3174}
3175 3175
3176#[test] 3176#[test]
3177fn trait_in_scope_with_inner_item() {
3178 check_infer(
3179 r#"
3180mod m {
3181 pub trait Tr {
3182 fn method(&self) -> u8 { 0 }
3183 }
3184
3185 impl Tr for () {}
3186}
3187
3188use m::Tr;
3189
3190fn f() {
3191 fn inner() {
3192 ().method();
3193 //^^^^^^^^^^^ u8
3194 }
3195}
3196 "#,
3197 expect![[r#"
3198 46..50 'self': &Self
3199 58..63 '{ 0 }': u8
3200 60..61 '0': u8
3201 115..185 '{ ... } }': ()
3202 132..183 '{ ... }': ()
3203 142..144 '()': ()
3204 142..153 '().method()': u8
3205 "#]],
3206 );
3207}
3208
3209#[test]
3177fn inner_use_in_block() { 3210fn inner_use_in_block() {
3178 check_types( 3211 check_types(
3179 r#" 3212 r#"
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 65b79df0d..7351e4e54 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -259,6 +259,6 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
259 match container { 259 match container {
260 AssocContainerId::ImplId(it) => Some(it.into()), 260 AssocContainerId::ImplId(it) => Some(it.into()),
261 AssocContainerId::TraitId(it) => Some(it.into()), 261 AssocContainerId::TraitId(it) => Some(it.into()),
262 AssocContainerId::ContainerId(_) => None, 262 AssocContainerId::ModuleId(_) => None,
263 } 263 }
264} 264}