aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/adt.rs21
-rw-r--r--crates/hir_def/src/attr.rs7
-rw-r--r--crates/hir_def/src/body.rs20
-rw-r--r--crates/hir_def/src/body/lower.rs177
-rw-r--r--crates/hir_def/src/body/scope.rs4
-rw-r--r--crates/hir_def/src/body/tests.rs3
-rw-r--r--crates/hir_def/src/body/tests/block.rs37
-rw-r--r--crates/hir_def/src/builtin_type.rs132
-rw-r--r--crates/hir_def/src/child_by_source.rs54
-rw-r--r--crates/hir_def/src/data.rs4
-rw-r--r--crates/hir_def/src/db.rs2
-rw-r--r--crates/hir_def/src/diagnostics.rs28
-rw-r--r--crates/hir_def/src/expr.rs3
-rw-r--r--crates/hir_def/src/find_path.rs87
-rw-r--r--crates/hir_def/src/generics.rs4
-rw-r--r--crates/hir_def/src/import_map.rs101
-rw-r--r--crates/hir_def/src/item_scope.rs56
-rw-r--r--crates/hir_def/src/item_tree.rs13
-rw-r--r--crates/hir_def/src/item_tree/lower.rs2
-rw-r--r--crates/hir_def/src/lib.rs187
-rw-r--r--crates/hir_def/src/nameres.rs26
-rw-r--r--crates/hir_def/src/nameres/collector.rs121
-rw-r--r--crates/hir_def/src/nameres/mod_resolution.rs3
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs46
-rw-r--r--crates/hir_def/src/nameres/tests.rs9
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs5
-rw-r--r--crates/hir_def/src/nameres/tests/globs.rs8
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs10
-rw-r--r--crates/hir_def/src/nameres/tests/mod_resolution.rs4
-rw-r--r--crates/hir_def/src/path/lower.rs13
-rw-r--r--crates/hir_def/src/path/lower/lower_use.rs3
-rw-r--r--crates/hir_def/src/resolver.rs53
-rw-r--r--crates/hir_def/src/test_db.rs9
33 files changed, 580 insertions, 672 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index ed36c3109..efbde17d8 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -21,8 +21,7 @@ use crate::{
21 trace::Trace, 21 trace::Trace,
22 type_ref::TypeRef, 22 type_ref::TypeRef,
23 visibility::RawVisibility, 23 visibility::RawVisibility,
24 EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, 24 EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
25 VariantId,
26}; 25};
27use cfg::CfgOptions; 26use cfg::CfgOptions;
28 27
@@ -92,10 +91,10 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
92impl StructData { 91impl StructData {
93 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 92 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
94 let loc = id.lookup(db); 93 let loc = id.lookup(db);
95 let krate = loc.container.module(db).krate; 94 let krate = loc.container.krate;
96 let item_tree = db.item_tree(loc.id.file_id); 95 let item_tree = db.item_tree(loc.id.file_id);
97 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); 96 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
98 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 97 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
99 98
100 let strukt = &item_tree[loc.id.value]; 99 let strukt = &item_tree[loc.id.value];
101 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None); 100 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
@@ -107,10 +106,10 @@ impl StructData {
107 } 106 }
108 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 107 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
109 let loc = id.lookup(db); 108 let loc = id.lookup(db);
110 let krate = loc.container.module(db).krate; 109 let krate = loc.container.krate;
111 let item_tree = db.item_tree(loc.id.file_id); 110 let item_tree = db.item_tree(loc.id.file_id);
112 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); 111 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
113 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 112 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
114 113
115 let union = &item_tree[loc.id.value]; 114 let union = &item_tree[loc.id.value];
116 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None); 115 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
@@ -126,7 +125,7 @@ impl StructData {
126impl EnumData { 125impl EnumData {
127 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { 126 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
128 let loc = e.lookup(db); 127 let loc = e.lookup(db);
129 let krate = loc.container.module(db).krate; 128 let krate = loc.container.krate;
130 let item_tree = db.item_tree(loc.id.file_id); 129 let item_tree = db.item_tree(loc.id.file_id);
131 let cfg_options = db.crate_graph()[krate].cfg_options.clone(); 130 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
132 131
@@ -168,7 +167,7 @@ impl HasChildSource<LocalEnumVariantId> for EnumId {
168 ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> { 167 ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
169 let src = self.lookup(db).source(db); 168 let src = self.lookup(db).source(db);
170 let mut trace = Trace::new_for_map(); 169 let mut trace = Trace::new_for_map();
171 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); 170 lower_enum(db, &mut trace, &src, self.lookup(db).container);
172 src.with_value(trace.into_map()) 171 src.with_value(trace.into_map())
173 } 172 }
174} 173}
@@ -238,10 +237,10 @@ impl HasChildSource<LocalFieldId> for VariantId {
238 // I don't really like the fact that we call into parent source 237 // I don't really like the fact that we call into parent source
239 // here, this might add to more queries then necessary. 238 // here, this might add to more queries then necessary.
240 let src = it.parent.child_source(db); 239 let src = it.parent.child_source(db);
241 (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container.module(db)) 240 (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container)
242 } 241 }
243 VariantId::StructId(it) => { 242 VariantId::StructId(it) => {
244 (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container.module(db)) 243 (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container)
245 } 244 }
246 VariantId::UnionId(it) => ( 245 VariantId::UnionId(it) => (
247 it.lookup(db).source(db).map(|it| { 246 it.lookup(db).source(db).map(|it| {
@@ -249,7 +248,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
249 .map(ast::StructKind::Record) 248 .map(ast::StructKind::Record)
250 .unwrap_or(ast::StructKind::Unit) 249 .unwrap_or(ast::StructKind::Unit)
251 }), 250 }),
252 it.lookup(db).container.module(db), 251 it.lookup(db).container,
253 ), 252 ),
254 }; 253 };
255 let mut expander = CfgExpander::new(db, src.file_id, module_id.krate); 254 let mut expander = CfgExpander::new(db, src.file_id, module_id.krate);
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index fe4c3fa28..97cdbbb9e 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -13,7 +13,6 @@ use syntax::{
13 ast::{self, AstNode, AttrsOwner}, 13 ast::{self, AstNode, AttrsOwner},
14 match_ast, AstToken, SmolStr, SyntaxNode, 14 match_ast, AstToken, SmolStr, SyntaxNode,
15}; 15};
16use test_utils::mark;
17use tt::Subtree; 16use tt::Subtree;
18 17
19use crate::{ 18use crate::{
@@ -177,7 +176,7 @@ impl RawAttrs {
177 if cfg_options.check(&cfg) == Some(false) { 176 if cfg_options.check(&cfg) == Some(false) {
178 None 177 None
179 } else { 178 } else {
180 mark::hit!(cfg_attr_active); 179 cov_mark::hit!(cfg_attr_active);
181 180
182 let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?; 181 let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?;
183 let hygiene = Hygiene::new_unhygienic(); // FIXME 182 let hygiene = Hygiene::new_unhygienic(); // FIXME
@@ -268,7 +267,7 @@ impl Attrs {
268 db: &dyn DefDatabase, 267 db: &dyn DefDatabase,
269 e: EnumId, 268 e: EnumId,
270 ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> { 269 ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
271 let krate = e.lookup(db).container.module(db).krate; 270 let krate = e.lookup(db).container.krate;
272 let src = e.child_source(db); 271 let src = e.child_source(db);
273 let mut res = ArenaMap::default(); 272 let mut res = ArenaMap::default();
274 273
@@ -367,7 +366,7 @@ fn inner_attributes(
367 // Excerpt from the reference: 366 // Excerpt from the reference:
368 // Block expressions accept outer and inner attributes, but only when they are the outer 367 // Block expressions accept outer and inner attributes, but only when they are the outer
369 // expression of an expression statement or the final expression of another block expression. 368 // expression of an expression statement or the final expression of another block expression.
370 ast::BlockExpr(it) => return None, 369 ast::BlockExpr(_it) => return None,
371 _ => return None, 370 _ => return None,
372 } 371 }
373 }; 372 };
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 9a432f7d1..19c4eb521 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -20,7 +20,6 @@ use la_arena::{Arena, ArenaMap};
20use profile::Count; 20use profile::Count;
21use rustc_hash::FxHashMap; 21use rustc_hash::FxHashMap;
22use syntax::{ast, AstNode, AstPtr}; 22use syntax::{ast, AstNode, AstPtr};
23use test_utils::mark;
24 23
25pub(crate) use lower::LowerCtx; 24pub(crate) use lower::LowerCtx;
26 25
@@ -29,11 +28,10 @@ use crate::{
29 db::DefDatabase, 28 db::DefDatabase,
30 expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, 29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
31 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
32 item_scope::ItemScope,
33 nameres::DefMap, 31 nameres::DefMap,
34 path::{ModPath, Path}, 32 path::{ModPath, Path},
35 src::HasSource, 33 src::HasSource,
36 AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, 34 AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId,
37}; 35};
38 36
39/// 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
@@ -87,11 +85,11 @@ impl Expander {
87 module: ModuleId, 85 module: ModuleId,
88 ) -> Expander { 86 ) -> Expander {
89 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); 87 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
90 let crate_def_map = module.def_map(db); 88 let def_map = module.def_map(db);
91 let ast_id_map = db.ast_id_map(current_file_id); 89 let ast_id_map = db.ast_id_map(current_file_id);
92 Expander { 90 Expander {
93 cfg_expander, 91 cfg_expander,
94 def_map: crate_def_map, 92 def_map,
95 current_file_id, 93 current_file_id,
96 ast_id_map, 94 ast_id_map,
97 module: module.local_id, 95 module: module.local_id,
@@ -105,7 +103,7 @@ impl Expander {
105 macro_call: ast::MacroCall, 103 macro_call: ast::MacroCall,
106 ) -> ExpandResult<Option<(Mark, T)>> { 104 ) -> ExpandResult<Option<(Mark, T)>> {
107 if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { 105 if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT {
108 mark::hit!(your_stack_belongs_to_me); 106 cov_mark::hit!(your_stack_belongs_to_me);
109 return ExpandResult::str_err("reached recursion limit during macro expansion".into()); 107 return ExpandResult::str_err("reached recursion limit during macro expansion".into());
110 } 108 }
111 109
@@ -123,7 +121,7 @@ impl Expander {
123 Some(it) => it, 121 Some(it) => it,
124 None => { 122 None => {
125 if err.is_none() { 123 if err.is_none() {
126 eprintln!("no error despite `as_call_id_with_errors` returning `None`"); 124 log::warn!("no error despite `as_call_id_with_errors` returning `None`");
127 } 125 }
128 return ExpandResult { value: None, err }; 126 return ExpandResult { value: None, err };
129 } 127 }
@@ -227,7 +225,8 @@ pub struct Body {
227 pub params: Vec<PatId>, 225 pub params: Vec<PatId>,
228 /// The `ExprId` of the actual body expression. 226 /// The `ExprId` of the actual body expression.
229 pub body_expr: ExprId, 227 pub body_expr: ExprId,
230 pub item_scope: ItemScope, 228 /// Block expressions in this body that may contain inner items.
229 pub block_scopes: Vec<BlockId>,
231 _c: Count<Self>, 230 _c: Count<Self>,
232} 231}
233 232
@@ -296,7 +295,7 @@ impl Body {
296 } 295 }
297 }; 296 };
298 let expander = Expander::new(db, file_id, module); 297 let expander = Expander::new(db, file_id, module);
299 let (body, source_map) = Body::new(db, def, expander, params, body); 298 let (body, source_map) = Body::new(db, expander, params, body);
300 (Arc::new(body), Arc::new(source_map)) 299 (Arc::new(body), Arc::new(source_map))
301 } 300 }
302 301
@@ -306,12 +305,11 @@ impl Body {
306 305
307 fn new( 306 fn new(
308 db: &dyn DefDatabase, 307 db: &dyn DefDatabase,
309 def: DefWithBodyId,
310 expander: Expander, 308 expander: Expander,
311 params: Option<ast::ParamList>, 309 params: Option<ast::ParamList>,
312 body: Option<ast::Expr>, 310 body: Option<ast::Expr>,
313 ) -> (Body, BodySourceMap) { 311 ) -> (Body, BodySourceMap) {
314 lower::lower(db, def, expander, params, body) 312 lower::lower(db, expander, params, body)
315 } 313 }
316} 314}
317 315
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index c18001e15..8c8eb8007 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -1,17 +1,16 @@
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;
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;
14use rustc_hash::FxHashMap;
15use syntax::{ 14use syntax::{
16 ast::{ 15 ast::{
17 self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner, 16 self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
@@ -19,12 +18,11 @@ use syntax::{
19 }, 18 },
20 AstNode, AstPtr, SyntaxNodePtr, 19 AstNode, AstPtr, SyntaxNodePtr,
21}; 20};
22use test_utils::mark;
23 21
24use crate::{ 22use crate::{
25 adt::StructKind, 23 adt::StructKind,
26 body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, 24 body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax},
27 builtin_type::{BuiltinFloat, BuiltinInt}, 25 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
28 db::DefDatabase, 26 db::DefDatabase,
29 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, 27 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
30 expr::{ 28 expr::{
@@ -33,11 +31,9 @@ use crate::{
33 Statement, 31 Statement,
34 }, 32 },
35 item_scope::BuiltinShadowMode, 33 item_scope::BuiltinShadowMode,
36 item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
37 path::{GenericArgs, Path}, 34 path::{GenericArgs, Path},
38 type_ref::{Mutability, Rawness, TypeRef}, 35 type_ref::{Mutability, Rawness, TypeRef},
39 AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, 36 AdtId, BlockLoc, ModuleDefId,
40 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
41}; 37};
42 38
43use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; 39use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
@@ -61,15 +57,12 @@ impl LowerCtx {
61 57
62pub(super) fn lower( 58pub(super) fn lower(
63 db: &dyn DefDatabase, 59 db: &dyn DefDatabase,
64 def: DefWithBodyId,
65 expander: Expander, 60 expander: Expander,
66 params: Option<ast::ParamList>, 61 params: Option<ast::ParamList>,
67 body: Option<ast::Expr>, 62 body: Option<ast::Expr>,
68) -> (Body, BodySourceMap) { 63) -> (Body, BodySourceMap) {
69 let item_tree = db.item_tree(expander.current_file_id);
70 ExprCollector { 64 ExprCollector {
71 db, 65 db,
72 def,
73 source_map: BodySourceMap::default(), 66 source_map: BodySourceMap::default(),
74 body: Body { 67 body: Body {
75 exprs: Arena::default(), 68 exprs: Arena::default(),
@@ -77,14 +70,9 @@ pub(super) fn lower(
77 labels: Arena::default(), 70 labels: Arena::default(),
78 params: Vec::new(), 71 params: Vec::new(),
79 body_expr: dummy_expr_id(), 72 body_expr: dummy_expr_id(),
80 item_scope: Default::default(), 73 block_scopes: Vec::new(),
81 _c: Count::new(), 74 _c: Count::new(),
82 }, 75 },
83 item_trees: {
84 let mut map = FxHashMap::default();
85 map.insert(expander.current_file_id, item_tree);
86 map
87 },
88 expander, 76 expander,
89 } 77 }
90 .collect(params, body) 78 .collect(params, body)
@@ -92,12 +80,9 @@ pub(super) fn lower(
92 80
93struct ExprCollector<'a> { 81struct ExprCollector<'a> {
94 db: &'a dyn DefDatabase, 82 db: &'a dyn DefDatabase,
95 def: DefWithBodyId,
96 expander: Expander, 83 expander: Expander,
97 body: Body, 84 body: Body,
98 source_map: BodySourceMap, 85 source_map: BodySourceMap,
99
100 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
101} 86}
102 87
103impl ExprCollector<'_> { 88impl ExprCollector<'_> {
@@ -286,7 +271,7 @@ impl ExprCollector<'_> {
286 None => self.collect_expr_opt(condition.expr()), 271 None => self.collect_expr_opt(condition.expr()),
287 // if let -- desugar to match 272 // if let -- desugar to match
288 Some(pat) => { 273 Some(pat) => {
289 mark::hit!(infer_resolve_while_let); 274 cov_mark::hit!(infer_resolve_while_let);
290 let pat = self.collect_pat(pat); 275 let pat = self.collect_pat(pat);
291 let match_expr = self.collect_expr_opt(condition.expr()); 276 let match_expr = self.collect_expr_opt(condition.expr());
292 let placeholder_pat = self.missing_pat(); 277 let placeholder_pat = self.missing_pat();
@@ -594,9 +579,6 @@ impl ExprCollector<'_> {
594 } else { 579 } else {
595 self.source_map.expansions.insert(macro_call, self.expander.current_file_id); 580 self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
596 581
597 let item_tree = self.db.item_tree(self.expander.current_file_id);
598 self.item_trees.insert(self.expander.current_file_id, item_tree);
599
600 let id = collector(self, Some(expansion)); 582 let id = collector(self, Some(expansion));
601 self.expander.exit(self.db, mark); 583 self.expander.exit(self.db, mark);
602 id 584 id
@@ -606,32 +588,6 @@ impl ExprCollector<'_> {
606 } 588 }
607 } 589 }
608 590
609 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
610 let id = self.expander.ast_id(ast);
611 let tree = &self.item_trees[&id.file_id];
612
613 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
614
615 // Root file (non-macro).
616 let item_tree_id = tree
617 .all_inner_items()
618 .chain(tree.top_level_items().iter().copied())
619 .filter_map(|mod_item| mod_item.downcast::<N>())
620 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
621 .or_else(|| {
622 log::debug!(
623 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
624 type_name::<N>(),
625 id,
626 ast.syntax(),
627 ast.syntax(),
628 );
629 None
630 })?;
631
632 Some(ItemTreeId::new(id.file_id, item_tree_id))
633 }
634
635 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 591 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
636 if let Some(expr) = expr { 592 if let Some(expr) = expr {
637 self.collect_expr(expr) 593 self.collect_expr(expr)
@@ -663,7 +619,6 @@ impl ExprCollector<'_> {
663 match expansion { 619 match expansion {
664 Some(expansion) => { 620 Some(expansion) => {
665 let statements: ast::MacroStmts = expansion; 621 let statements: ast::MacroStmts = expansion;
666 this.collect_stmts_items(statements.statements());
667 622
668 statements.statements().for_each(|stmt| { 623 statements.statements().for_each(|stmt| {
669 if let Some(mut r) = this.collect_stmt(stmt) { 624 if let Some(mut r) = this.collect_stmt(stmt) {
@@ -701,6 +656,8 @@ impl ExprCollector<'_> {
701 let block_loc = 656 let block_loc =
702 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 657 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
703 let block_id = self.db.intern_block(block_loc); 658 let block_id = self.db.intern_block(block_loc);
659 self.body.block_scopes.push(block_id);
660
704 let opt_def_map = self.db.block_def_map(block_id); 661 let opt_def_map = self.db.block_def_map(block_id);
705 let has_def_map = opt_def_map.is_some(); 662 let has_def_map = opt_def_map.is_some();
706 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 663 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
@@ -708,7 +665,6 @@ impl ExprCollector<'_> {
708 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 665 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
709 let prev_local_module = mem::replace(&mut self.expander.module, module); 666 let prev_local_module = mem::replace(&mut self.expander.module, module);
710 667
711 self.collect_stmts_items(block.statements());
712 let statements = 668 let statements =
713 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); 669 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
714 let tail = block.tail_expr().map(|e| self.collect_expr(e)); 670 let tail = block.tail_expr().map(|e| self.collect_expr(e));
@@ -723,108 +679,6 @@ impl ExprCollector<'_> {
723 expr_id 679 expr_id
724 } 680 }
725 681
726 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
727 let container = ContainerId::DefWithBodyId(self.def);
728
729 let items = stmts
730 .filter_map(|stmt| match stmt {
731 ast::Stmt::Item(it) => Some(it),
732 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
733 })
734 .filter_map(|item| {
735 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
736 ast::Item::Fn(def) => {
737 let id = self.find_inner_item(&def)?;
738 (
739 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
740 def.name(),
741 )
742 }
743 ast::Item::TypeAlias(def) => {
744 let id = self.find_inner_item(&def)?;
745 (
746 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
747 def.name(),
748 )
749 }
750 ast::Item::Const(def) => {
751 let id = self.find_inner_item(&def)?;
752 (
753 ConstLoc { container: container.into(), id }.intern(self.db).into(),
754 def.name(),
755 )
756 }
757 ast::Item::Static(def) => {
758 let id = self.find_inner_item(&def)?;
759 (StaticLoc { container, id }.intern(self.db).into(), def.name())
760 }
761 ast::Item::Struct(def) => {
762 let id = self.find_inner_item(&def)?;
763 (StructLoc { container, id }.intern(self.db).into(), def.name())
764 }
765 ast::Item::Enum(def) => {
766 let id = self.find_inner_item(&def)?;
767 (EnumLoc { container, id }.intern(self.db).into(), def.name())
768 }
769 ast::Item::Union(def) => {
770 let id = self.find_inner_item(&def)?;
771 (UnionLoc { container, id }.intern(self.db).into(), def.name())
772 }
773 ast::Item::Trait(def) => {
774 let id = self.find_inner_item(&def)?;
775 (TraitLoc { container, id }.intern(self.db).into(), def.name())
776 }
777 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
778 ast::Item::Impl(_)
779 | ast::Item::Use(_)
780 | ast::Item::ExternCrate(_)
781 | ast::Item::Module(_)
782 | ast::Item::MacroCall(_) => return None,
783 ast::Item::MacroRules(def) => {
784 return Some(Either::Right(ast::Macro::from(def)));
785 }
786 ast::Item::MacroDef(def) => {
787 return Some(Either::Right(ast::Macro::from(def)));
788 }
789 };
790
791 Some(Either::Left((def, name)))
792 })
793 .collect::<Vec<_>>();
794
795 for either in items {
796 match either {
797 Either::Left((def, name)) => {
798 self.body.item_scope.define_def(def);
799 if let Some(name) = name {
800 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
801 let has_constructor = match def {
802 ModuleDefId::AdtId(AdtId::StructId(s)) => {
803 self.db.struct_data(s).variant_data.kind() != StructKind::Record
804 }
805 _ => true,
806 };
807 self.body.item_scope.push_res(
808 name.as_name(),
809 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
810 );
811 }
812 }
813 Either::Right(e) => {
814 let mac = MacroDefId {
815 krate: self.expander.def_map.krate(),
816 ast_id: Some(self.expander.ast_id(&e)),
817 kind: MacroDefKind::Declarative,
818 local_inner: false,
819 };
820 if let Some(name) = e.name() {
821 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
822 }
823 }
824 }
825 }
826 }
827
828 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 682 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
829 if let Some(block) = expr { 683 if let Some(block) = expr {
830 self.collect_block(block) 684 self.collect_block(block)
@@ -1065,11 +919,16 @@ impl From<ast::LiteralKind> for Literal {
1065 fn from(ast_lit_kind: ast::LiteralKind) -> Self { 919 fn from(ast_lit_kind: ast::LiteralKind) -> Self {
1066 match ast_lit_kind { 920 match ast_lit_kind {
1067 LiteralKind::IntNumber(lit) => { 921 LiteralKind::IntNumber(lit) => {
1068 if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { 922 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
1069 return Literal::Float(Default::default(), Some(float_suffix)); 923 return Literal::Float(Default::default(), builtin);
924 } else if let builtin @ Some(_) =
925 lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
926 {
927 Literal::Int(Default::default(), builtin)
928 } else {
929 let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
930 Literal::Uint(Default::default(), builtin)
1070 } 931 }
1071 let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it));
1072 Literal::Int(Default::default(), ty)
1073 } 932 }
1074 LiteralKind::FloatNumber(lit) => { 933 LiteralKind::FloatNumber(lit) => {
1075 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); 934 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it));
@@ -1077,7 +936,7 @@ impl From<ast::LiteralKind> for Literal {
1077 } 936 }
1078 LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), 937 LiteralKind::ByteString(_) => Literal::ByteString(Default::default()),
1079 LiteralKind::String(_) => Literal::String(Default::default()), 938 LiteralKind::String(_) => Literal::String(Default::default()),
1080 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), 939 LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
1081 LiteralKind::Bool(val) => Literal::Bool(val), 940 LiteralKind::Bool(val) => Literal::Bool(val),
1082 LiteralKind::Char => Literal::Char(Default::default()), 941 LiteralKind::Char => Literal::Char(Default::default()),
1083 } 942 }
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs
index 210b4a617..1bbb54fc6 100644
--- a/crates/hir_def/src/body/scope.rs
+++ b/crates/hir_def/src/body/scope.rs
@@ -186,7 +186,7 @@ mod tests {
186 use base_db::{fixture::WithFixture, FileId, SourceDatabase}; 186 use base_db::{fixture::WithFixture, FileId, SourceDatabase};
187 use hir_expand::{name::AsName, InFile}; 187 use hir_expand::{name::AsName, InFile};
188 use syntax::{algo::find_node_at_offset, ast, AstNode}; 188 use syntax::{algo::find_node_at_offset, ast, AstNode};
189 use test_utils::{assert_eq_text, extract_offset, mark}; 189 use test_utils::{assert_eq_text, extract_offset};
190 190
191 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; 191 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
192 192
@@ -454,7 +454,7 @@ fn foo() {
454 454
455 #[test] 455 #[test]
456 fn while_let_desugaring() { 456 fn while_let_desugaring() {
457 mark::check!(infer_resolve_while_let); 457 cov_mark::check!(infer_resolve_while_let);
458 do_check_local_name( 458 do_check_local_name(
459 r#" 459 r#"
460fn test() { 460fn test() {
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index bb43569d7..991a32b15 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -2,7 +2,6 @@ mod block;
2 2
3use base_db::{fixture::WithFixture, SourceDatabase}; 3use base_db::{fixture::WithFixture, SourceDatabase};
4use expect_test::Expect; 4use expect_test::Expect;
5use test_utils::mark;
6 5
7use crate::{test_db::TestDB, ModuleDefId}; 6use crate::{test_db::TestDB, ModuleDefId};
8 7
@@ -48,7 +47,7 @@ fn check_at(ra_fixture: &str, expect: Expect) {
48 47
49#[test] 48#[test]
50fn your_stack_belongs_to_me() { 49fn your_stack_belongs_to_me() {
51 mark::check!(your_stack_belongs_to_me); 50 cov_mark::check!(your_stack_belongs_to_me);
52 lower( 51 lower(
53 " 52 "
54macro_rules! n_nuple { 53macro_rules! n_nuple {
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs
index a5ec0883f..3b6ba4cde 100644
--- a/crates/hir_def/src/body/tests/block.rs
+++ b/crates/hir_def/src/body/tests/block.rs
@@ -165,16 +165,16 @@ fn macro_resolve() {
165 check_at( 165 check_at(
166 r#" 166 r#"
167//- /lib.rs crate:lib deps:core 167//- /lib.rs crate:lib deps:core
168use core::mark; 168use core::cov_mark;
169 169
170fn f() { 170fn f() {
171 fn nested() { 171 fn nested() {
172 mark::hit!(Hit); 172 cov_mark::hit!(Hit);
173 $0 173 $0
174 } 174 }
175} 175}
176//- /core.rs crate:core 176//- /core.rs crate:core
177pub mod mark { 177pub mod cov_mark {
178 #[macro_export] 178 #[macro_export]
179 macro_rules! _hit { 179 macro_rules! _hit {
180 ($name:ident) => { 180 ($name:ident) => {
@@ -193,8 +193,8 @@ pub mod mark {
193 nested: v 193 nested: v
194 194
195 crate 195 crate
196 cov_mark: t
196 f: v 197 f: v
197 mark: t
198 "#]], 198 "#]],
199 ); 199 );
200} 200}
@@ -259,3 +259,32 @@ fn main() {
259 "#]], 259 "#]],
260 ); 260 );
261} 261}
262
263#[test]
264fn underscore_import() {
265 // This used to panic, because the default (private) visibility inside block expressions would
266 // point into the containing `DefMap`, which visibilities should never be able to do.
267 cov_mark::check!(adjust_vis_in_block_def_map);
268 check_at(
269 r#"
270mod m {
271 fn main() {
272 use Tr as _;
273 trait Tr {}
274 $0
275 }
276}
277 "#,
278 expect![[r#"
279 block scope
280 _: t
281 Tr: t
282
283 crate
284 m: t
285
286 crate::m
287 main: v
288 "#]],
289 );
290}
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs
index 0f872b5c0..7cbaf30b8 100644
--- a/crates/hir_def/src/builtin_type.rs
+++ b/crates/hir_def/src/builtin_type.rs
@@ -6,38 +6,32 @@
6use std::fmt; 6use std::fmt;
7 7
8use hir_expand::name::{name, AsName, Name}; 8use hir_expand::name::{name, AsName, Name};
9 9/// Different signed int types.
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 10#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub enum Signedness { 11pub enum BuiltinInt {
12 Signed, 12 Isize,
13 Unsigned, 13 I8,
14} 14 I16,
15 15 I32,
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 16 I64,
17pub enum IntBitness { 17 I128,
18 Xsize,
19 X8,
20 X16,
21 X32,
22 X64,
23 X128,
24}
25
26#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
27pub enum FloatBitness {
28 X32,
29 X64,
30} 18}
31 19
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 20/// Different unsigned int types.
33pub struct BuiltinInt { 21#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
34 pub signedness: Signedness, 22pub enum BuiltinUint {
35 pub bitness: IntBitness, 23 Usize,
24 U8,
25 U16,
26 U32,
27 U64,
28 U128,
36} 29}
37 30
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 31#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct BuiltinFloat { 32pub enum BuiltinFloat {
40 pub bitness: FloatBitness, 33 F32,
34 F64,
41} 35}
42 36
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -46,6 +40,7 @@ pub enum BuiltinType {
46 Bool, 40 Bool,
47 Str, 41 Str,
48 Int(BuiltinInt), 42 Int(BuiltinInt),
43 Uint(BuiltinUint),
49 Float(BuiltinFloat), 44 Float(BuiltinFloat),
50} 45}
51 46
@@ -56,19 +51,19 @@ impl BuiltinType {
56 (name![bool], BuiltinType::Bool), 51 (name![bool], BuiltinType::Bool),
57 (name![str], BuiltinType::Str), 52 (name![str], BuiltinType::Str),
58 53
59 (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), 54 (name![isize], BuiltinType::Int(BuiltinInt::Isize)),
60 (name![i8], BuiltinType::Int(BuiltinInt::I8)), 55 (name![i8], BuiltinType::Int(BuiltinInt::I8)),
61 (name![i16], BuiltinType::Int(BuiltinInt::I16)), 56 (name![i16], BuiltinType::Int(BuiltinInt::I16)),
62 (name![i32], BuiltinType::Int(BuiltinInt::I32)), 57 (name![i32], BuiltinType::Int(BuiltinInt::I32)),
63 (name![i64], BuiltinType::Int(BuiltinInt::I64)), 58 (name![i64], BuiltinType::Int(BuiltinInt::I64)),
64 (name![i128], BuiltinType::Int(BuiltinInt::I128)), 59 (name![i128], BuiltinType::Int(BuiltinInt::I128)),
65 60
66 (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), 61 (name![usize], BuiltinType::Uint(BuiltinUint::Usize)),
67 (name![u8], BuiltinType::Int(BuiltinInt::U8)), 62 (name![u8], BuiltinType::Uint(BuiltinUint::U8)),
68 (name![u16], BuiltinType::Int(BuiltinInt::U16)), 63 (name![u16], BuiltinType::Uint(BuiltinUint::U16)),
69 (name![u32], BuiltinType::Int(BuiltinInt::U32)), 64 (name![u32], BuiltinType::Uint(BuiltinUint::U32)),
70 (name![u64], BuiltinType::Int(BuiltinInt::U64)), 65 (name![u64], BuiltinType::Uint(BuiltinUint::U64)),
71 (name![u128], BuiltinType::Int(BuiltinInt::U128)), 66 (name![u128], BuiltinType::Uint(BuiltinUint::U128)),
72 67
73 (name![f32], BuiltinType::Float(BuiltinFloat::F32)), 68 (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
74 (name![f64], BuiltinType::Float(BuiltinFloat::F64)), 69 (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
@@ -81,24 +76,25 @@ impl AsName for BuiltinType {
81 BuiltinType::Char => name![char], 76 BuiltinType::Char => name![char],
82 BuiltinType::Bool => name![bool], 77 BuiltinType::Bool => name![bool],
83 BuiltinType::Str => name![str], 78 BuiltinType::Str => name![str],
84 BuiltinType::Int(BuiltinInt { signedness, bitness }) => match (signedness, bitness) { 79 BuiltinType::Int(it) => match it {
85 (Signedness::Signed, IntBitness::Xsize) => name![isize], 80 BuiltinInt::Isize => name![isize],
86 (Signedness::Signed, IntBitness::X8) => name![i8], 81 BuiltinInt::I8 => name![i8],
87 (Signedness::Signed, IntBitness::X16) => name![i16], 82 BuiltinInt::I16 => name![i16],
88 (Signedness::Signed, IntBitness::X32) => name![i32], 83 BuiltinInt::I32 => name![i32],
89 (Signedness::Signed, IntBitness::X64) => name![i64], 84 BuiltinInt::I64 => name![i64],
90 (Signedness::Signed, IntBitness::X128) => name![i128], 85 BuiltinInt::I128 => name![i128],
91 86 },
92 (Signedness::Unsigned, IntBitness::Xsize) => name![usize], 87 BuiltinType::Uint(it) => match it {
93 (Signedness::Unsigned, IntBitness::X8) => name![u8], 88 BuiltinUint::Usize => name![usize],
94 (Signedness::Unsigned, IntBitness::X16) => name![u16], 89 BuiltinUint::U8 => name![u8],
95 (Signedness::Unsigned, IntBitness::X32) => name![u32], 90 BuiltinUint::U16 => name![u16],
96 (Signedness::Unsigned, IntBitness::X64) => name![u64], 91 BuiltinUint::U32 => name![u32],
97 (Signedness::Unsigned, IntBitness::X128) => name![u128], 92 BuiltinUint::U64 => name![u64],
93 BuiltinUint::U128 => name![u128],
98 }, 94 },
99 BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { 95 BuiltinType::Float(it) => match it {
100 FloatBitness::X32 => name![f32], 96 BuiltinFloat::F32 => name![f32],
101 FloatBitness::X64 => name![f64], 97 BuiltinFloat::F64 => name![f64],
102 }, 98 },
103 } 99 }
104 } 100 }
@@ -113,31 +109,26 @@ impl fmt::Display for BuiltinType {
113 109
114#[rustfmt::skip] 110#[rustfmt::skip]
115impl BuiltinInt { 111impl BuiltinInt {
116 pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize };
117 pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 };
118 pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 };
119 pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 };
120 pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 };
121 pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 };
122
123 pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize };
124 pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 };
125 pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 };
126 pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 };
127 pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 };
128 pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 };
129
130
131 pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { 112 pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> {
132 let res = match suffix { 113 let res = match suffix {
133 "isize" => Self::ISIZE, 114 "isize" => Self::Isize,
134 "i8" => Self::I8, 115 "i8" => Self::I8,
135 "i16" => Self::I16, 116 "i16" => Self::I16,
136 "i32" => Self::I32, 117 "i32" => Self::I32,
137 "i64" => Self::I64, 118 "i64" => Self::I64,
138 "i128" => Self::I128, 119 "i128" => Self::I128,
139 120
140 "usize" => Self::USIZE, 121 _ => return None,
122 };
123 Some(res)
124 }
125}
126
127#[rustfmt::skip]
128impl BuiltinUint {
129 pub fn from_suffix(suffix: &str) -> Option<BuiltinUint> {
130 let res = match suffix {
131 "usize" => Self::Usize,
141 "u8" => Self::U8, 132 "u8" => Self::U8,
142 "u16" => Self::U16, 133 "u16" => Self::U16,
143 "u32" => Self::U32, 134 "u32" => Self::U32,
@@ -152,9 +143,6 @@ impl BuiltinInt {
152 143
153#[rustfmt::skip] 144#[rustfmt::skip]
154impl BuiltinFloat { 145impl BuiltinFloat {
155 pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 };
156 pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 };
157
158 pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { 146 pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> {
159 let res = match suffix { 147 let res = match suffix {
160 "f32" => BuiltinFloat::F32, 148 "f32" => BuiltinFloat::F32,
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index 65d85c86a..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 crate_def_map = self.def_map(db); 74 let def_map = self.def_map(db);
78 let module_data = &crate_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/data.rs b/crates/hir_def/src/data.rs
index d3380e0f4..aea53d527 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -97,7 +97,7 @@ impl TraitData {
97 let tr_def = &item_tree[tr_loc.id.value]; 97 let tr_def = &item_tree[tr_loc.id.value];
98 let name = tr_def.name.clone(); 98 let name = tr_def.name.clone();
99 let auto = tr_def.auto; 99 let auto = tr_def.auto;
100 let module_id = tr_loc.container.module(db); 100 let module_id = tr_loc.container;
101 let container = AssocContainerId::TraitId(tr); 101 let container = AssocContainerId::TraitId(tr);
102 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); 102 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
103 103
@@ -147,7 +147,7 @@ impl ImplData {
147 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); 147 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
148 let target_type = item_tree[impl_def.target_type].clone(); 148 let target_type = item_tree[impl_def.target_type].clone();
149 let is_negative = impl_def.is_negative; 149 let is_negative = impl_def.is_negative;
150 let module_id = impl_loc.container.module(db); 150 let module_id = impl_loc.container;
151 let container = AssocContainerId::ImplId(id); 151 let container = AssocContainerId::ImplId(id);
152 let mut expander = Expander::new(db, impl_loc.id.file_id, module_id); 152 let mut expander = Expander::new(db, impl_loc.id.file_id, module_id);
153 153
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 6c01f1ed0..cca5a086b 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -133,7 +133,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
133 fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; 133 fn import_map(&self, krate: CrateId) -> Arc<ImportMap>;
134} 134}
135 135
136fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<DefMap> { 136fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
137 let _p = profile::span("crate_def_map:wait"); 137 let _p = profile::span("crate_def_map:wait");
138 db.crate_def_map_query(krate) 138 db.crate_def_map_query(krate)
139} 139}
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs
index ab3f059ce..ac7474f63 100644
--- a/crates/hir_def/src/diagnostics.rs
+++ b/crates/hir_def/src/diagnostics.rs
@@ -95,6 +95,34 @@ impl Diagnostic for UnresolvedImport {
95 } 95 }
96} 96}
97 97
98// Diagnostic: unresolved-macro-call
99//
100// This diagnostic is triggered if rust-analyzer is unable to resolove path to a
101// macro in a macro invocation.
102#[derive(Debug)]
103pub struct UnresolvedMacroCall {
104 pub file: HirFileId,
105 pub node: AstPtr<ast::MacroCall>,
106}
107
108impl Diagnostic for UnresolvedMacroCall {
109 fn code(&self) -> DiagnosticCode {
110 DiagnosticCode("unresolved-macro-call")
111 }
112 fn message(&self) -> String {
113 "unresolved macro call".to_string()
114 }
115 fn display_source(&self) -> InFile<SyntaxNodePtr> {
116 InFile::new(self.file, self.node.clone().into())
117 }
118 fn as_any(&self) -> &(dyn Any + Send + 'static) {
119 self
120 }
121 fn is_experimental(&self) -> bool {
122 true
123 }
124}
125
98// Diagnostic: inactive-code 126// Diagnostic: inactive-code
99// 127//
100// This diagnostic is shown for code with inactive `#[cfg]` attributes. 128// This diagnostic is shown for code with inactive `#[cfg]` attributes.
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 4d72eaeaf..24be93773 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -17,7 +17,7 @@ use la_arena::{Idx, RawIdx};
17use syntax::ast::RangeOp; 17use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 path::{GenericArgs, Path}, 21 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 22 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 23 BlockId,
@@ -43,6 +43,7 @@ pub enum Literal {
43 Char(char), 43 Char(char),
44 Bool(bool), 44 Bool(bool),
45 Int(u64, Option<BuiltinInt>), 45 Int(u64, Option<BuiltinInt>),
46 Uint(u64, Option<BuiltinUint>),
46 Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq 47 Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
47} 48}
48 49
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 5e2a711b8..de08e2737 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -1,8 +1,9 @@
1//! An algorithm to find a path to refer to a certain item. 1//! An algorithm to find a path to refer to a certain item.
2 2
3use std::iter;
4
3use hir_expand::name::{known, AsName, Name}; 5use hir_expand::name::{known, AsName, Name};
4use rustc_hash::FxHashSet; 6use rustc_hash::FxHashSet;
5use test_utils::mark;
6 7
7use crate::nameres::DefMap; 8use crate::nameres::DefMap;
8use crate::{ 9use crate::{
@@ -95,7 +96,7 @@ fn find_path_inner(
95 item: ItemInNs, 96 item: ItemInNs,
96 from: ModuleId, 97 from: ModuleId,
97 max_len: usize, 98 max_len: usize,
98 prefixed: Option<PrefixKind>, 99 mut prefixed: Option<PrefixKind>,
99) -> Option<ModPath> { 100) -> Option<ModPath> {
100 if max_len == 0 { 101 if max_len == 0 {
101 return None; 102 return None;
@@ -114,8 +115,9 @@ fn find_path_inner(
114 } 115 }
115 116
116 // - if the item is the crate root, return `crate` 117 // - if the item is the crate root, return `crate`
117 let root = def_map.module_id(def_map.root()); 118 let root = def_map.crate_root(db);
118 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { 119 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() {
120 // FIXME: the `block_id()` check should be unnecessary, but affects the result
119 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 121 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
120 } 122 }
121 123
@@ -165,7 +167,7 @@ fn find_path_inner(
165 167
166 // - otherwise, look for modules containing (reexporting) it and import it from one of those 168 // - otherwise, look for modules containing (reexporting) it and import it from one of those
167 169
168 let crate_root = def_map.module_id(def_map.root()); 170 let crate_root = def_map.crate_root(db);
169 let crate_attrs = db.attrs(crate_root.into()); 171 let crate_attrs = db.attrs(crate_root.into());
170 let prefer_no_std = crate_attrs.by_key("no_std").exists(); 172 let prefer_no_std = crate_attrs.by_key("no_std").exists();
171 let mut best_path = None; 173 let mut best_path = None;
@@ -212,7 +214,7 @@ fn find_path_inner(
212 best_path_len - 1, 214 best_path_len - 1,
213 prefixed, 215 prefixed,
214 )?; 216 )?;
215 mark::hit!(partially_imported); 217 cov_mark::hit!(partially_imported);
216 path.push_segment(info.path.segments.last().unwrap().clone()); 218 path.push_segment(info.path.segments.last().unwrap().clone());
217 Some(path) 219 Some(path)
218 }) 220 })
@@ -228,12 +230,16 @@ fn find_path_inner(
228 } 230 }
229 } 231 }
230 232
231 if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) { 233 // If the item is declared inside a block expression, don't use a prefix, as we don't handle
232 if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() { 234 // that correctly (FIXME).
233 // Inner items cannot be referred to via `crate::` or `self::` paths. 235 if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) {
234 prefix = PathKind::Plain; 236 if item_module.def_map(db).block_id().is_some() && prefixed.is_some() {
237 cov_mark::hit!(prefixed_in_block_expression);
238 prefixed = Some(PrefixKind::Plain);
235 } 239 }
240 }
236 241
242 if let Some(prefix) = prefixed.map(PrefixKind::prefix) {
237 best_path.or_else(|| { 243 best_path.or_else(|| {
238 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) 244 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name]))
239 }) 245 })
@@ -245,18 +251,18 @@ fn find_path_inner(
245fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { 251fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath {
246 if old_path.starts_with_std() && new_path.can_start_with_std() { 252 if old_path.starts_with_std() && new_path.can_start_with_std() {
247 if prefer_no_std { 253 if prefer_no_std {
248 mark::hit!(prefer_no_std_paths); 254 cov_mark::hit!(prefer_no_std_paths);
249 new_path 255 new_path
250 } else { 256 } else {
251 mark::hit!(prefer_std_paths); 257 cov_mark::hit!(prefer_std_paths);
252 old_path 258 old_path
253 } 259 }
254 } else if new_path.starts_with_std() && old_path.can_start_with_std() { 260 } else if new_path.starts_with_std() && old_path.can_start_with_std() {
255 if prefer_no_std { 261 if prefer_no_std {
256 mark::hit!(prefer_no_std_paths); 262 cov_mark::hit!(prefer_no_std_paths);
257 old_path 263 old_path
258 } else { 264 } else {
259 mark::hit!(prefer_std_paths); 265 cov_mark::hit!(prefer_std_paths);
260 new_path 266 new_path
261 } 267 }
262 } else if new_path.len() < old_path.len() { 268 } else if new_path.len() < old_path.len() {
@@ -285,12 +291,12 @@ fn find_local_import_locations(
285 let data = &def_map[from.local_id]; 291 let data = &def_map[from.local_id];
286 let mut worklist = 292 let mut worklist =
287 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); 293 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>();
288 let mut parent = data.parent; 294 for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) {
289 while let Some(p) = parent { 295 worklist.push(ancestor);
290 worklist.push(def_map.module_id(p));
291 parent = def_map[p].parent;
292 } 296 }
293 297
298 let def_map = def_map.crate_root(db).def_map(db);
299
294 let mut seen: FxHashSet<_> = FxHashSet::default(); 300 let mut seen: FxHashSet<_> = FxHashSet::default();
295 301
296 let mut locations = Vec::new(); 302 let mut locations = Vec::new();
@@ -301,7 +307,14 @@ fn find_local_import_locations(
301 307
302 let ext_def_map; 308 let ext_def_map;
303 let data = if module.krate == from.krate { 309 let data = if module.krate == from.krate {
304 &def_map[module.local_id] 310 if module.block.is_some() {
311 // Re-query the block's DefMap
312 ext_def_map = module.def_map(db);
313 &ext_def_map[module.local_id]
314 } else {
315 // Reuse the root DefMap
316 &def_map[module.local_id]
317 }
305 } else { 318 } else {
306 // The crate might reexport a module defined in another crate. 319 // The crate might reexport a module defined in another crate.
307 ext_def_map = module.def_map(db); 320 ext_def_map = module.def_map(db);
@@ -350,7 +363,6 @@ mod tests {
350 use base_db::fixture::WithFixture; 363 use base_db::fixture::WithFixture;
351 use hir_expand::hygiene::Hygiene; 364 use hir_expand::hygiene::Hygiene;
352 use syntax::ast::AstNode; 365 use syntax::ast::AstNode;
353 use test_utils::mark;
354 366
355 use crate::test_db::TestDB; 367 use crate::test_db::TestDB;
356 368
@@ -508,7 +520,7 @@ mod tests {
508 520
509 #[test] 521 #[test]
510 fn partially_imported() { 522 fn partially_imported() {
511 mark::check!(partially_imported); 523 cov_mark::check!(partially_imported);
512 // Tests that short paths are used even for external items, when parts of the path are 524 // Tests that short paths are used even for external items, when parts of the path are
513 // already in scope. 525 // already in scope.
514 let code = r#" 526 let code = r#"
@@ -672,7 +684,7 @@ mod tests {
672 684
673 #[test] 685 #[test]
674 fn prefer_std_paths_over_alloc() { 686 fn prefer_std_paths_over_alloc() {
675 mark::check!(prefer_std_paths); 687 cov_mark::check!(prefer_std_paths);
676 let code = r#" 688 let code = r#"
677 //- /main.rs crate:main deps:alloc,std 689 //- /main.rs crate:main deps:alloc,std
678 $0 690 $0
@@ -698,7 +710,7 @@ mod tests {
698 710
699 #[test] 711 #[test]
700 fn prefer_core_paths_over_std() { 712 fn prefer_core_paths_over_std() {
701 mark::check!(prefer_no_std_paths); 713 cov_mark::check!(prefer_no_std_paths);
702 let code = r#" 714 let code = r#"
703 //- /main.rs crate:main deps:core,std 715 //- /main.rs crate:main deps:core,std
704 #![no_std] 716 #![no_std]
@@ -828,6 +840,7 @@ mod tests {
828 840
829 #[test] 841 #[test]
830 fn inner_items_from_inner_module() { 842 fn inner_items_from_inner_module() {
843 cov_mark::check!(prefixed_in_block_expression);
831 check_found_path( 844 check_found_path(
832 r#" 845 r#"
833 fn main() { 846 fn main() {
@@ -847,26 +860,22 @@ mod tests {
847 } 860 }
848 861
849 #[test] 862 #[test]
850 #[ignore] 863 fn outer_items_with_inner_items_present() {
851 fn inner_items_from_parent_module() {
852 // FIXME: ItemTree currently associates all inner items with `main`. Luckily, this sort of
853 // code is very rare, so this isn't terrible.
854 // To fix it, we should probably build dedicated `ItemTree`s for inner items, and not store
855 // them in the file's main ItemTree. This would also allow us to stop parsing function
856 // bodies when we only want to compute the crate's main DefMap.
857 check_found_path( 864 check_found_path(
858 r#" 865 r#"
866 mod module {
867 pub struct CompleteMe;
868 }
869
859 fn main() { 870 fn main() {
860 struct Struct {} 871 fn inner() {}
861 mod module { 872 $0
862 $0
863 }
864 } 873 }
865 "#, 874 "#,
866 "super::Struct", 875 "module::CompleteMe",
867 "super::Struct", 876 "module::CompleteMe",
868 "super::Struct", 877 "crate::module::CompleteMe",
869 "super::Struct", 878 "self::module::CompleteMe",
870 ); 879 )
871 } 880 }
872} 881}
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/import_map.rs b/crates/hir_def/src/import_map.rs
index 0a3dc7956..369bc3350 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -8,7 +8,6 @@ use hir_expand::name::Name;
8use indexmap::{map::Entry, IndexMap}; 8use indexmap::{map::Entry, IndexMap};
9use itertools::Itertools; 9use itertools::Itertools;
10use rustc_hash::{FxHashSet, FxHasher}; 10use rustc_hash::{FxHashSet, FxHasher};
11use test_utils::mark;
12 11
13use crate::{ 12use crate::{
14 db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, 13 db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId,
@@ -193,7 +192,7 @@ impl ImportMap {
193 // cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias` 192 // cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
194 // qualifier, ergo no need to store it for imports in import_map 193 // qualifier, ergo no need to store it for imports in import_map
195 AssocItemId::TypeAliasId(_) => { 194 AssocItemId::TypeAliasId(_) => {
196 mark::hit!(type_aliases_ignored); 195 cov_mark::hit!(type_aliases_ignored);
197 continue; 196 continue;
198 } 197 }
199 }; 198 };
@@ -388,7 +387,7 @@ pub fn search_dependencies<'a>(
388 db: &'a dyn DefDatabase, 387 db: &'a dyn DefDatabase,
389 krate: CrateId, 388 krate: CrateId,
390 query: Query, 389 query: Query,
391) -> Vec<ItemInNs> { 390) -> FxHashSet<ItemInNs> {
392 let _p = profile::span("search_dependencies").detail(|| format!("{:?}", query)); 391 let _p = profile::span("search_dependencies").detail(|| format!("{:?}", query));
393 392
394 let graph = db.crate_graph(); 393 let graph = db.crate_graph();
@@ -403,41 +402,42 @@ pub fn search_dependencies<'a>(
403 } 402 }
404 403
405 let mut stream = op.union(); 404 let mut stream = op.union();
406 let mut res = Vec::new(); 405
406 let mut all_indexed_values = FxHashSet::default();
407 while let Some((_, indexed_values)) = stream.next() { 407 while let Some((_, indexed_values)) = stream.next() {
408 for indexed_value in indexed_values { 408 all_indexed_values.extend(indexed_values.iter().copied());
409 let import_map = &import_maps[indexed_value.index]; 409 }
410 let importables = &import_map.importables[indexed_value.value as usize..];
411 410
412 let common_importable_data = &import_map.map[&importables[0]]; 411 let mut res = FxHashSet::default();
413 if !query.import_matches(common_importable_data, true) { 412 for indexed_value in all_indexed_values {
414 continue; 413 let import_map = &import_maps[indexed_value.index];
415 } 414 let importables = &import_map.importables[indexed_value.value as usize..];
416 415
417 // Path shared by the importable items in this group. 416 let common_importable_data = &import_map.map[&importables[0]];
418 let common_importables_path_fst = fst_path(&common_importable_data.path); 417 if !query.import_matches(common_importable_data, true) {
419 // Add the items from this `ModPath` group. Those are all subsequent items in 418 continue;
420 // `importables` whose paths match `path`. 419 }
421 let iter = importables 420
422 .iter() 421 // Path shared by the importable items in this group.
423 .copied() 422 let common_importables_path_fst = fst_path(&common_importable_data.path);
424 .take_while(|item| { 423 // Add the items from this `ModPath` group. Those are all subsequent items in
425 common_importables_path_fst == fst_path(&import_map.map[item].path) 424 // `importables` whose paths match `path`.
426 }) 425 let iter = importables
427 .filter(|&item| match item_import_kind(item) { 426 .iter()
428 Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind), 427 .copied()
429 None => true, 428 .take_while(|item| common_importables_path_fst == fst_path(&import_map.map[item].path))
430 }) 429 .filter(|&item| match item_import_kind(item) {
431 .filter(|item| { 430 Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind),
432 !query.case_sensitive // we've already checked the common importables path case-insensitively 431 None => true,
432 })
433 .filter(|item| {
434 !query.case_sensitive // we've already checked the common importables path case-insensitively
433 || query.import_matches(&import_map.map[item], false) 435 || query.import_matches(&import_map.map[item], false)
434 }); 436 });
435 res.extend(iter); 437 res.extend(iter);
436 438
437 if res.len() >= query.limit { 439 if res.len() >= query.limit {
438 res.truncate(query.limit); 440 return res;
439 return res;
440 }
441 } 441 }
442 } 442 }
443 443
@@ -462,7 +462,6 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
462mod tests { 462mod tests {
463 use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; 463 use base_db::{fixture::WithFixture, SourceDatabase, Upcast};
464 use expect_test::{expect, Expect}; 464 use expect_test::{expect, Expect};
465 use test_utils::mark;
466 465
467 use crate::{test_db::TestDB, AssocContainerId, Lookup}; 466 use crate::{test_db::TestDB, AssocContainerId, Lookup};
468 467
@@ -800,7 +799,7 @@ mod tests {
800 799
801 #[test] 800 #[test]
802 fn fuzzy_import_trait_and_assoc_items() { 801 fn fuzzy_import_trait_and_assoc_items() {
803 mark::check!(type_aliases_ignored); 802 cov_mark::check!(type_aliases_ignored);
804 let ra_fixture = r#" 803 let ra_fixture = r#"
805 //- /main.rs crate:main deps:dep 804 //- /main.rs crate:main deps:dep
806 //- /dep.rs crate:dep 805 //- /dep.rs crate:dep
@@ -821,10 +820,10 @@ mod tests {
821 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy), 820 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy),
822 expect![[r#" 821 expect![[r#"
823 dep::fmt (t) 822 dep::fmt (t)
823 dep::fmt::Display::format_method (a)
824 dep::fmt::Display (t) 824 dep::fmt::Display (t)
825 dep::fmt::Display::FMT_CONST (a) 825 dep::fmt::Display::FMT_CONST (a)
826 dep::fmt::Display::format_function (a) 826 dep::fmt::Display::format_function (a)
827 dep::fmt::Display::format_method (a)
828 "#]], 827 "#]],
829 ); 828 );
830 } 829 }
@@ -850,9 +849,9 @@ mod tests {
850 "main", 849 "main",
851 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy).assoc_items_only(), 850 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy).assoc_items_only(),
852 expect![[r#" 851 expect![[r#"
852 dep::fmt::Display::format_method (a)
853 dep::fmt::Display::FMT_CONST (a) 853 dep::fmt::Display::FMT_CONST (a)
854 dep::fmt::Display::format_function (a) 854 dep::fmt::Display::format_function (a)
855 dep::fmt::Display::format_method (a)
856 "#]], 855 "#]],
857 ); 856 );
858 857
@@ -911,12 +910,12 @@ mod tests {
911 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy), 910 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy),
912 expect![[r#" 911 expect![[r#"
913 dep::fmt (t) 912 dep::fmt (t)
914 dep::Fmt (t) 913 dep::format (f)
915 dep::Fmt (v) 914 dep::Fmt (v)
916 dep::Fmt (m)
917 dep::fmt::Display (t) 915 dep::fmt::Display (t)
916 dep::Fmt (t)
918 dep::fmt::Display::fmt (a) 917 dep::fmt::Display::fmt (a)
919 dep::format (f) 918 dep::Fmt (m)
920 "#]], 919 "#]],
921 ); 920 );
922 921
@@ -926,10 +925,10 @@ mod tests {
926 Query::new("fmt".to_string()).search_mode(SearchMode::Equals), 925 Query::new("fmt".to_string()).search_mode(SearchMode::Equals),
927 expect![[r#" 926 expect![[r#"
928 dep::fmt (t) 927 dep::fmt (t)
929 dep::Fmt (t)
930 dep::Fmt (v) 928 dep::Fmt (v)
931 dep::Fmt (m) 929 dep::Fmt (t)
932 dep::fmt::Display::fmt (a) 930 dep::fmt::Display::fmt (a)
931 dep::Fmt (m)
933 "#]], 932 "#]],
934 ); 933 );
935 934
@@ -939,11 +938,11 @@ mod tests {
939 Query::new("fmt".to_string()).search_mode(SearchMode::Contains), 938 Query::new("fmt".to_string()).search_mode(SearchMode::Contains),
940 expect![[r#" 939 expect![[r#"
941 dep::fmt (t) 940 dep::fmt (t)
942 dep::Fmt (t)
943 dep::Fmt (v) 941 dep::Fmt (v)
944 dep::Fmt (m)
945 dep::fmt::Display (t) 942 dep::fmt::Display (t)
943 dep::Fmt (t)
946 dep::fmt::Display::fmt (a) 944 dep::fmt::Display::fmt (a)
945 dep::Fmt (m)
947 "#]], 946 "#]],
948 ); 947 );
949 } 948 }
@@ -980,11 +979,11 @@ mod tests {
980 Query::new("fmt".to_string()), 979 Query::new("fmt".to_string()),
981 expect![[r#" 980 expect![[r#"
982 dep::fmt (t) 981 dep::fmt (t)
983 dep::Fmt (t)
984 dep::Fmt (v) 982 dep::Fmt (v)
985 dep::Fmt (m)
986 dep::fmt::Display (t) 983 dep::fmt::Display (t)
984 dep::Fmt (t)
987 dep::fmt::Display::fmt (a) 985 dep::fmt::Display::fmt (a)
986 dep::Fmt (m)
988 "#]], 987 "#]],
989 ); 988 );
990 989
@@ -994,10 +993,10 @@ mod tests {
994 Query::new("fmt".to_string()).name_only(), 993 Query::new("fmt".to_string()).name_only(),
995 expect![[r#" 994 expect![[r#"
996 dep::fmt (t) 995 dep::fmt (t)
997 dep::Fmt (t)
998 dep::Fmt (v) 996 dep::Fmt (v)
999 dep::Fmt (m) 997 dep::Fmt (t)
1000 dep::fmt::Display::fmt (a) 998 dep::fmt::Display::fmt (a)
999 dep::Fmt (m)
1001 "#]], 1000 "#]],
1002 ); 1001 );
1003 } 1002 }
@@ -1018,9 +1017,9 @@ mod tests {
1018 Query::new("FMT".to_string()), 1017 Query::new("FMT".to_string()),
1019 expect![[r#" 1018 expect![[r#"
1020 dep::fmt (t) 1019 dep::fmt (t)
1020 dep::FMT (v)
1021 dep::fmt (v) 1021 dep::fmt (v)
1022 dep::FMT (t) 1022 dep::FMT (t)
1023 dep::FMT (v)
1024 "#]], 1023 "#]],
1025 ); 1024 );
1026 1025
@@ -1060,6 +1059,8 @@ mod tests {
1060 expect![[r#" 1059 expect![[r#"
1061 dep::fmt (t) 1060 dep::fmt (t)
1062 dep::Fmt (t) 1061 dep::Fmt (t)
1062 dep::Fmt (m)
1063 dep::Fmt (v)
1063 "#]], 1064 "#]],
1064 ); 1065 );
1065 } 1066 }
@@ -1080,9 +1081,9 @@ mod tests {
1080 Query::new("FMT".to_string()), 1081 Query::new("FMT".to_string()),
1081 expect![[r#" 1082 expect![[r#"
1082 dep::fmt (t) 1083 dep::fmt (t)
1084 dep::FMT (v)
1083 dep::fmt (v) 1085 dep::fmt (v)
1084 dep::FMT (t) 1086 dep::FMT (t)
1085 dep::FMT (v)
1086 "#]], 1087 "#]],
1087 ); 1088 );
1088 1089
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index ee46c3330..aafd73b60 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -9,11 +9,10 @@ use hir_expand::MacroDefKind;
9use once_cell::sync::Lazy; 9use once_cell::sync::Lazy;
10use rustc_hash::{FxHashMap, FxHashSet}; 10use rustc_hash::{FxHashMap, FxHashSet};
11use stdx::format_to; 11use stdx::format_to;
12use test_utils::mark;
13 12
14use crate::{ 13use crate::{
15 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, 14 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId,
16 LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, 15 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
17}; 16};
18 17
19#[derive(Copy, Clone)] 18#[derive(Copy, Clone)]
@@ -169,37 +168,6 @@ impl ItemScope {
169 self.unnamed_trait_imports.insert(tr, vis); 168 self.unnamed_trait_imports.insert(tr, vis);
170 } 169 }
171 170
172 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
173 let mut changed = false;
174
175 if let Some(types) = def.types {
176 self.types.entry(name.clone()).or_insert_with(|| {
177 changed = true;
178 types
179 });
180 }
181 if let Some(values) = def.values {
182 self.values.entry(name.clone()).or_insert_with(|| {
183 changed = true;
184 values
185 });
186 }
187 if let Some(macros) = def.macros {
188 self.macros.entry(name.clone()).or_insert_with(|| {
189 changed = true;
190 macros
191 });
192 }
193
194 if def.is_none() {
195 if self.unresolved.insert(name) {
196 changed = true;
197 }
198 }
199
200 changed
201 }
202
203 pub(crate) fn push_res_with_import( 171 pub(crate) fn push_res_with_import(
204 &mut self, 172 &mut self,
205 glob_imports: &mut PerNsGlobImports, 173 glob_imports: &mut PerNsGlobImports,
@@ -237,7 +205,7 @@ impl ItemScope {
237 if $glob_imports.$field.contains(&$lookup) 205 if $glob_imports.$field.contains(&$lookup)
238 && matches!($def_import_type, ImportType::Named) => 206 && matches!($def_import_type, ImportType::Named) =>
239 { 207 {
240 mark::hit!(import_shadowed); 208 cov_mark::hit!(import_shadowed);
241 $glob_imports.$field.remove(&$lookup); 209 $glob_imports.$field.remove(&$lookup);
242 if let Some(fld) = $def.$field { 210 if let Some(fld) = $def.$field {
243 entry.insert(fld); 211 entry.insert(fld);
@@ -375,19 +343,9 @@ impl ItemInNs {
375 343
376 /// Returns the crate defining this item (or `None` if `self` is built-in). 344 /// Returns the crate defining this item (or `None` if `self` is built-in).
377 pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { 345 pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
378 Some(match self { 346 match self {
379 ItemInNs::Types(did) | ItemInNs::Values(did) => match did { 347 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate),
380 ModuleDefId::ModuleId(id) => id.krate, 348 ItemInNs::Macros(id) => Some(id.krate),
381 ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, 349 }
382 ModuleDefId::AdtId(id) => id.module(db).krate,
383 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate,
384 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate,
385 ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate,
386 ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate,
387 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
388 ModuleDefId::BuiltinType(_) => return None,
389 },
390 ItemInNs::Macros(id) => return Some(id.krate),
391 })
392 } 350 }
393} 351}
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 3233b1957..09bcb10dc 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -25,7 +25,6 @@ use profile::Count;
25use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
26use smallvec::SmallVec; 26use smallvec::SmallVec;
27use syntax::{ast, match_ast, SyntaxKind}; 27use syntax::{ast, match_ast, SyntaxKind};
28use test_utils::mark;
29 28
30use crate::{ 29use crate::{
31 attr::{Attrs, RawAttrs}, 30 attr::{Attrs, RawAttrs},
@@ -210,18 +209,6 @@ impl ItemTree {
210 } 209 }
211 } 210 }
212 211
213 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
214 // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty
215 // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with).
216 let root =
217 db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree");
218
219 let id = self[of.value].ast_id();
220 let map = db.ast_id_map(of.file_id);
221 let ptr = map.get(id);
222 ptr.to_node(&root)
223 }
224
225 fn data(&self) -> &ItemTreeData { 212 fn data(&self) -> &ItemTreeData {
226 self.data.as_ref().expect("attempted to access data of empty ItemTree") 213 self.data.as_ref().expect("attempted to access data of empty ItemTree")
227 } 214 }
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 8f2f0b340..240fdacf9 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -466,7 +466,7 @@ impl Ctx {
466 .collect() 466 .collect()
467 }) 467 })
468 .unwrap_or_else(|| { 468 .unwrap_or_else(|| {
469 mark::hit!(name_res_works_for_broken_modules); 469 cov_mark::hit!(name_res_works_for_broken_modules);
470 Box::new([]) as Box<[_]> 470 Box::new([]) as Box<[_]>
471 }), 471 }),
472 } 472 }
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index b50923747..6d11c5be4 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -57,8 +57,10 @@ use std::{
57 57
58use base_db::{impl_intern_key, salsa, CrateId}; 58use base_db::{impl_intern_key, salsa, CrateId};
59use hir_expand::{ 59use hir_expand::{
60 ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, 60 ast_id_map::FileAstId,
61 MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 61 eager::{expand_eager_macro, ErrorEmitted},
62 hygiene::Hygiene,
63 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
62}; 64};
63use la_arena::Idx; 65use la_arena::Idx;
64use nameres::DefMap; 66use nameres::DefMap;
@@ -95,6 +97,10 @@ impl ModuleId {
95 pub fn krate(&self) -> CrateId { 97 pub fn krate(&self) -> CrateId {
96 self.krate 98 self.krate
97 } 99 }
100
101 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
102 self.def_map(db).containing_module(self.local_id)
103 }
98} 104}
99 105
100/// An ID of a module, **local** to a specific crate 106/// An ID of a module, **local** to a specific crate
@@ -102,7 +108,7 @@ pub type LocalModuleId = Idx<nameres::ModuleData>;
102 108
103#[derive(Debug)] 109#[derive(Debug)]
104pub struct ItemLoc<N: ItemTreeNode> { 110pub struct ItemLoc<N: ItemTreeNode> {
105 pub container: ContainerId, 111 pub container: ModuleId,
106 pub id: ItemTreeId<N>, 112 pub id: ItemTreeId<N>,
107} 113}
108 114
@@ -273,18 +279,12 @@ pub struct ConstParamId {
273pub type LocalConstParamId = Idx<generics::ConstParamData>; 279pub type LocalConstParamId = Idx<generics::ConstParamData>;
274 280
275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 281#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
276pub enum ContainerId {
277 ModuleId(ModuleId),
278 DefWithBodyId(DefWithBodyId),
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
282pub enum AssocContainerId { 282pub enum AssocContainerId {
283 ContainerId(ContainerId), 283 ModuleId(ModuleId),
284 ImplId(ImplId), 284 ImplId(ImplId),
285 TraitId(TraitId), 285 TraitId(TraitId),
286} 286}
287impl_from!(ContainerId for AssocContainerId); 287impl_from!(ModuleId for AssocContainerId);
288 288
289/// A Data Type 289/// A Data Type
290#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 290#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -441,21 +441,12 @@ pub trait HasModule {
441 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId; 441 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
442} 442}
443 443
444impl HasModule for ContainerId {
445 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
446 match *self {
447 ContainerId::ModuleId(it) => it,
448 ContainerId::DefWithBodyId(it) => it.module(db),
449 }
450 }
451}
452
453impl HasModule for AssocContainerId { 444impl HasModule for AssocContainerId {
454 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 445 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
455 match *self { 446 match *self {
456 AssocContainerId::ContainerId(it) => it.module(db), 447 AssocContainerId::ModuleId(it) => it,
457 AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), 448 AssocContainerId::ImplId(it) => it.lookup(db).container,
458 AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), 449 AssocContainerId::TraitId(it) => it.lookup(db).container,
459 } 450 }
460 } 451 }
461} 452}
@@ -473,16 +464,15 @@ impl HasModule for AdtId {
473 AdtId::UnionId(it) => it.lookup(db).container, 464 AdtId::UnionId(it) => it.lookup(db).container,
474 AdtId::EnumId(it) => it.lookup(db).container, 465 AdtId::EnumId(it) => it.lookup(db).container,
475 } 466 }
476 .module(db)
477 } 467 }
478} 468}
479 469
480impl HasModule for VariantId { 470impl HasModule for VariantId {
481 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 471 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
482 match self { 472 match self {
483 VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), 473 VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
484 VariantId::StructId(it) => it.lookup(db).container.module(db), 474 VariantId::StructId(it) => it.lookup(db).container,
485 VariantId::UnionId(it) => it.lookup(db).container.module(db), 475 VariantId::UnionId(it) => it.lookup(db).container,
486 } 476 }
487 } 477 }
488} 478}
@@ -512,18 +502,37 @@ impl HasModule for GenericDefId {
512 match self { 502 match self {
513 GenericDefId::FunctionId(it) => it.lookup(db).module(db), 503 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
514 GenericDefId::AdtId(it) => it.module(db), 504 GenericDefId::AdtId(it) => it.module(db),
515 GenericDefId::TraitId(it) => it.lookup(db).container.module(db), 505 GenericDefId::TraitId(it) => it.lookup(db).container,
516 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), 506 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
517 GenericDefId::ImplId(it) => it.lookup(db).container.module(db), 507 GenericDefId::ImplId(it) => it.lookup(db).container,
518 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), 508 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
519 GenericDefId::ConstId(it) => it.lookup(db).module(db), 509 GenericDefId::ConstId(it) => it.lookup(db).module(db),
520 } 510 }
521 } 511 }
522} 512}
523 513
524impl HasModule for StaticLoc { 514impl HasModule for StaticLoc {
525 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 515 fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId {
526 self.container.module(db) 516 self.container
517 }
518}
519
520impl ModuleDefId {
521 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
522 ///
523 /// Returns `None` if `self` refers to a primitive type.
524 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
525 Some(match self {
526 ModuleDefId::ModuleId(id) => *id,
527 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
528 ModuleDefId::AdtId(id) => id.module(db),
529 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container,
530 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
531 ModuleDefId::StaticId(id) => id.lookup(db).container,
532 ModuleDefId::TraitId(id) => id.lookup(db).container,
533 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
534 ModuleDefId::BuiltinType(_) => return None,
535 })
527 } 536 }
528} 537}
529 538
@@ -534,12 +543,12 @@ impl AttrDefId {
534 AttrDefId::FieldId(it) => it.parent.module(db).krate, 543 AttrDefId::FieldId(it) => it.parent.module(db).krate,
535 AttrDefId::AdtId(it) => it.module(db).krate, 544 AttrDefId::AdtId(it) => it.module(db).krate,
536 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, 545 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
537 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate, 546 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate,
538 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, 547 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
539 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, 548 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
540 AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, 549 AttrDefId::TraitId(it) => it.lookup(db).container.krate,
541 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, 550 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
542 AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, 551 AttrDefId::ImplId(it) => it.lookup(db).container.krate,
543 AttrDefId::GenericParamId(it) => { 552 AttrDefId::GenericParamId(it) => {
544 match it { 553 match it {
545 GenericParamId::TypeParamId(it) => it.parent, 554 GenericParamId::TypeParamId(it) => it.parent,
@@ -592,8 +601,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
592 error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); 601 error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
593 } 602 }
594 603
595 AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) 604 macro_call_as_call_id(
596 .as_call_id_with_errors(db, krate, resolver, error_sink) 605 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?),
606 db,
607 krate,
608 resolver,
609 error_sink,
610 )
611 .ok()?
612 .ok()
597 } 613 }
598} 614}
599 615
@@ -610,61 +626,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
610 } 626 }
611} 627}
612 628
613impl AsMacroCall for AstIdWithPath<ast::MacroCall> { 629struct UnresolvedMacro;
614 fn as_call_id_with_errors( 630
615 &self, 631fn macro_call_as_call_id(
616 db: &dyn db::DefDatabase, 632 call: &AstIdWithPath<ast::MacroCall>,
617 krate: CrateId, 633 db: &dyn db::DefDatabase,
618 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 634 krate: CrateId,
619 error_sink: &mut dyn FnMut(mbe::ExpandError), 635 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
620 ) -> Option<MacroCallId> { 636 error_sink: &mut dyn FnMut(mbe::ExpandError),
621 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 637) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
622 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 638 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
623 None 639
624 })?; 640 let res = if let MacroDefKind::BuiltInEager(_) = def.kind {
625 641 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
626 if let MacroDefKind::BuiltInEager(_) = def.kind { 642 let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);
627 let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); 643
628 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); 644 expand_eager_macro(
629 645 db.upcast(),
630 Some( 646 krate,
631 expand_eager_macro( 647 macro_call,
632 db.upcast(), 648 def,
633 krate, 649 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
634 macro_call, 650 error_sink,
635 def, 651 )
636 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), 652 .map(MacroCallId::from)
637 error_sink, 653 } else {
638 ) 654 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
639 .ok()? 655 };
640 .into(), 656 Ok(res)
641 )
642 } else {
643 Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
644 }
645 }
646} 657}
647 658
648impl AsMacroCall for AstIdWithPath<ast::Item> { 659fn item_attr_as_call_id(
649 fn as_call_id_with_errors( 660 item_attr: &AstIdWithPath<ast::Item>,
650 &self, 661 db: &dyn db::DefDatabase,
651 db: &dyn db::DefDatabase, 662 krate: CrateId,
652 krate: CrateId, 663 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
653 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 664) -> Result<MacroCallId, UnresolvedMacro> {
654 error_sink: &mut dyn FnMut(mbe::ExpandError), 665 let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
655 ) -> Option<MacroCallId> { 666 let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
656 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 667 let res = def
657 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 668 .as_lazy_macro(
658 None 669 db.upcast(),
659 })?; 670 krate,
660 671 MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()),
661 Some(
662 def.as_lazy_macro(
663 db.upcast(),
664 krate,
665 MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()),
666 )
667 .into(),
668 ) 672 )
669 } 673 .into();
674 Ok(res)
670} 675}
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index f92232eb3..003d668ca 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -343,6 +343,18 @@ impl DefMap {
343 Some(self.block?.parent) 343 Some(self.block?.parent)
344 } 344 }
345 345
346 /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing
347 /// the block, if `self` corresponds to a block expression.
348 pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
349 match &self[local_mod].parent {
350 Some(parent) => Some(self.module_id(*parent)),
351 None => match &self.block {
352 Some(block) => Some(block.parent),
353 None => None,
354 },
355 }
356 }
357
346 // FIXME: this can use some more human-readable format (ideally, an IR 358 // FIXME: this can use some more human-readable format (ideally, an IR
347 // even), as this should be a great debugging aid. 359 // even), as this should be a great debugging aid.
348 pub fn dump(&self, db: &dyn DefDatabase) -> String { 360 pub fn dump(&self, db: &dyn DefDatabase) -> String {
@@ -417,6 +429,8 @@ mod diagnostics {
417 429
418 UnresolvedProcMacro { ast: MacroCallKind }, 430 UnresolvedProcMacro { ast: MacroCallKind },
419 431
432 UnresolvedMacroCall { ast: AstId<ast::MacroCall> },
433
420 MacroError { ast: MacroCallKind, message: String }, 434 MacroError { ast: MacroCallKind, message: String },
421 } 435 }
422 436
@@ -477,6 +491,13 @@ mod diagnostics {
477 Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } 491 Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } }
478 } 492 }
479 493
494 pub(super) fn unresolved_macro_call(
495 container: LocalModuleId,
496 ast: AstId<ast::MacroCall>,
497 ) -> Self {
498 Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast } }
499 }
500
480 pub(super) fn add_to( 501 pub(super) fn add_to(
481 &self, 502 &self,
482 db: &dyn DefDatabase, 503 db: &dyn DefDatabase,
@@ -589,6 +610,11 @@ mod diagnostics {
589 }); 610 });
590 } 611 }
591 612
613 DiagnosticKind::UnresolvedMacroCall { ast } => {
614 let node = ast.to_node(db.upcast());
615 sink.push(UnresolvedMacroCall { file: ast.file_id, node: AstPtr::new(&node) });
616 }
617
592 DiagnosticKind::MacroError { ast, message } => { 618 DiagnosticKind::MacroError { ast, message } => {
593 let (file, ast) = match ast { 619 let (file, ast) = match ast {
594 MacroCallKind::FnLike(ast) => { 620 MacroCallKind::FnLike(ast) => {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 9996a0807..9ed48c506 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,22 +13,23 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
20use syntax::ast; 20use syntax::ast;
21use test_utils::mark;
22use tt::{Leaf, TokenTree}; 21use tt::{Leaf, TokenTree};
23 22
24use crate::{ 23use crate::{
25 attr::Attrs, 24 attr::Attrs,
26 db::DefDatabase, 25 db::DefDatabase,
26 item_attr_as_call_id,
27 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{ 28 item_tree::{
29 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, 29 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
30 StructDefKind, 30 StructDefKind,
31 }, 31 },
32 macro_call_as_call_id,
32 nameres::{ 33 nameres::{
33 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 34 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
34 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, 35 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -36,9 +37,9 @@ use crate::{
36 path::{ImportAlias, ModPath, PathKind}, 37 path::{ImportAlias, ModPath, PathKind},
37 per_ns::PerNs, 38 per_ns::PerNs,
38 visibility::{RawVisibility, Visibility}, 39 visibility::{RawVisibility, Visibility},
39 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, 40 AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
40 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, 41 LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
41 TypeAliasLoc, UnionLoc, 42 UnresolvedMacro,
42}; 43};
43 44
44const GLOB_RECURSION_LIMIT: usize = 100; 45const GLOB_RECURSION_LIMIT: usize = 100;
@@ -460,7 +461,7 @@ impl DefCollector<'_> {
460 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); 461 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name);
461 462
462 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 463 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
463 mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 464 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
464 self.import_all_macros_exported(current_module_id, m.krate); 465 self.import_all_macros_exported(current_module_id, m.krate);
465 } 466 }
466 } 467 }
@@ -569,10 +570,10 @@ impl DefCollector<'_> {
569 match def.take_types() { 570 match def.take_types() {
570 Some(ModuleDefId::ModuleId(m)) => { 571 Some(ModuleDefId::ModuleId(m)) => {
571 if import.is_prelude { 572 if import.is_prelude {
572 mark::hit!(std_prelude); 573 cov_mark::hit!(std_prelude);
573 self.def_map.prelude = Some(m); 574 self.def_map.prelude = Some(m);
574 } else if m.krate != self.def_map.krate { 575 } else if m.krate != self.def_map.krate {
575 mark::hit!(glob_across_crates); 576 cov_mark::hit!(glob_across_crates);
576 // glob import from other crate => we can just import everything once 577 // glob import from other crate => we can just import everything once
577 let item_map = m.def_map(self.db); 578 let item_map = m.def_map(self.db);
578 let scope = &item_map[m.local_id].scope; 579 let scope = &item_map[m.local_id].scope;
@@ -624,7 +625,7 @@ impl DefCollector<'_> {
624 } 625 }
625 } 626 }
626 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 627 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
627 mark::hit!(glob_enum); 628 cov_mark::hit!(glob_enum);
628 // glob import from enum => just import all the variants 629 // glob import from enum => just import all the variants
629 630
630 // XXX: urgh, so this works by accident! Here, we look at 631 // XXX: urgh, so this works by accident! Here, we look at
@@ -673,7 +674,7 @@ impl DefCollector<'_> {
673 674
674 self.update(module_id, &[(name, def)], vis, ImportType::Named); 675 self.update(module_id, &[(name, def)], vis, ImportType::Named);
675 } 676 }
676 None => mark::hit!(bogus_paths), 677 None => cov_mark::hit!(bogus_paths),
677 } 678 }
678 } 679 }
679 } 680 }
@@ -736,7 +737,7 @@ impl DefCollector<'_> {
736 if max_vis == old_vis { 737 if max_vis == old_vis {
737 false 738 false
738 } else { 739 } else {
739 mark::hit!(upgrade_underscore_visibility); 740 cov_mark::hit!(upgrade_underscore_visibility);
740 true 741 true
741 } 742 }
742 } 743 }
@@ -790,8 +791,11 @@ impl DefCollector<'_> {
790 return false; 791 return false;
791 } 792 }
792 793
793 if let Some(call_id) = 794 match macro_call_as_call_id(
794 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { 795 &directive.ast_id,
796 self.db,
797 self.def_map.krate,
798 |path| {
795 let resolved_res = self.def_map.resolve_path_fp_with_macro( 799 let resolved_res = self.def_map.resolve_path_fp_with_macro(
796 self.db, 800 self.db,
797 ResolveMode::Other, 801 ResolveMode::Other,
@@ -800,24 +804,29 @@ impl DefCollector<'_> {
800 BuiltinShadowMode::Module, 804 BuiltinShadowMode::Module,
801 ); 805 );
802 resolved_res.resolved_def.take_macros() 806 resolved_res.resolved_def.take_macros()
803 }) 807 },
804 { 808 &mut |_err| (),
805 resolved.push((directive.module_id, call_id, directive.depth)); 809 ) {
806 res = ReachedFixedPoint::No; 810 Ok(Ok(call_id)) => {
807 return false; 811 resolved.push((directive.module_id, call_id, directive.depth));
812 res = ReachedFixedPoint::No;
813 return false;
814 }
815 Err(UnresolvedMacro) | Ok(Err(_)) => {}
808 } 816 }
809 817
810 true 818 true
811 }); 819 });
812 attribute_macros.retain(|directive| { 820 attribute_macros.retain(|directive| {
813 if let Some(call_id) = 821 match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| {
814 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { 822 self.resolve_attribute_macro(&directive, &path)
815 self.resolve_attribute_macro(&directive, &path) 823 }) {
816 }) 824 Ok(call_id) => {
817 { 825 resolved.push((directive.module_id, call_id, 0));
818 resolved.push((directive.module_id, call_id, 0)); 826 res = ReachedFixedPoint::No;
819 res = ReachedFixedPoint::No; 827 return false;
820 return false; 828 }
829 Err(UnresolvedMacro) => (),
821 } 830 }
822 831
823 true 832 true
@@ -856,7 +865,7 @@ impl DefCollector<'_> {
856 depth: usize, 865 depth: usize,
857 ) { 866 ) {
858 if depth > EXPANSION_DEPTH_LIMIT { 867 if depth > EXPANSION_DEPTH_LIMIT {
859 mark::hit!(macro_expansion_overflow); 868 cov_mark::hit!(macro_expansion_overflow);
860 log::warn!("macro expansion is too deep"); 869 log::warn!("macro expansion is too deep");
861 return; 870 return;
862 } 871 }
@@ -902,7 +911,8 @@ impl DefCollector<'_> {
902 911
903 for directive in &self.unexpanded_macros { 912 for directive in &self.unexpanded_macros {
904 let mut error = None; 913 let mut error = None;
905 directive.ast_id.as_call_id_with_errors( 914 match macro_call_as_call_id(
915 &directive.ast_id,
906 self.db, 916 self.db,
907 self.def_map.krate, 917 self.def_map.krate,
908 |path| { 918 |path| {
@@ -918,15 +928,15 @@ impl DefCollector<'_> {
918 &mut |e| { 928 &mut |e| {
919 error.get_or_insert(e); 929 error.get_or_insert(e);
920 }, 930 },
921 ); 931 ) {
922 932 Ok(_) => (),
923 if let Some(err) = error { 933 Err(UnresolvedMacro) => {
924 self.def_map.diagnostics.push(DefDiagnostic::macro_error( 934 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
925 directive.module_id, 935 directive.module_id,
926 MacroCallKind::FnLike(directive.ast_id.ast_id), 936 directive.ast_id.ast_id,
927 err.to_string(), 937 ));
928 )); 938 }
929 } 939 };
930 } 940 }
931 941
932 // Emit diagnostics for all remaining unresolved imports. 942 // Emit diagnostics for all remaining unresolved imports.
@@ -998,7 +1008,7 @@ impl ModCollector<'_, '_> {
998 // Prelude module is always considered to be `#[macro_use]`. 1008 // Prelude module is always considered to be `#[macro_use]`.
999 if let Some(prelude_module) = self.def_collector.def_map.prelude { 1009 if let Some(prelude_module) = self.def_collector.def_map.prelude {
1000 if prelude_module.krate != self.def_collector.def_map.krate { 1010 if prelude_module.krate != self.def_collector.def_map.krate {
1001 mark::hit!(prelude_is_macro_use); 1011 cov_mark::hit!(prelude_is_macro_use);
1002 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); 1012 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1003 } 1013 }
1004 } 1014 }
@@ -1032,7 +1042,6 @@ impl ModCollector<'_, '_> {
1032 } 1042 }
1033 } 1043 }
1034 let module = self.def_collector.def_map.module_id(self.module_id); 1044 let module = self.def_collector.def_map.module_id(self.module_id);
1035 let container = ContainerId::ModuleId(module);
1036 1045
1037 let mut def = None; 1046 let mut def = None;
1038 match item { 1047 match item {
@@ -1099,9 +1108,9 @@ impl ModCollector<'_, '_> {
1099 } 1108 }
1100 ModItem::Impl(imp) => { 1109 ModItem::Impl(imp) => {
1101 let module = self.def_collector.def_map.module_id(self.module_id); 1110 let module = self.def_collector.def_map.module_id(self.module_id);
1102 let container = ContainerId::ModuleId(module); 1111 let impl_id =
1103 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } 1112 ImplLoc { container: module, id: ItemTreeId::new(self.file_id, imp) }
1104 .intern(self.def_collector.db); 1113 .intern(self.def_collector.db);
1105 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) 1114 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1106 } 1115 }
1107 ModItem::Function(id) => { 1116 ModItem::Function(id) => {
@@ -1111,7 +1120,7 @@ impl ModCollector<'_, '_> {
1111 1120
1112 def = Some(DefData { 1121 def = Some(DefData {
1113 id: FunctionLoc { 1122 id: FunctionLoc {
1114 container: container.into(), 1123 container: module.into(),
1115 id: ItemTreeId::new(self.file_id, id), 1124 id: ItemTreeId::new(self.file_id, id),
1116 } 1125 }
1117 .intern(self.def_collector.db) 1126 .intern(self.def_collector.db)
@@ -1130,7 +1139,7 @@ impl ModCollector<'_, '_> {
1130 self.collect_derives(&attrs, it.ast_id.upcast()); 1139 self.collect_derives(&attrs, it.ast_id.upcast());
1131 1140
1132 def = Some(DefData { 1141 def = Some(DefData {
1133 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } 1142 id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1134 .intern(self.def_collector.db) 1143 .intern(self.def_collector.db)
1135 .into(), 1144 .into(),
1136 name: &it.name, 1145 name: &it.name,
@@ -1147,7 +1156,7 @@ impl ModCollector<'_, '_> {
1147 self.collect_derives(&attrs, it.ast_id.upcast()); 1156 self.collect_derives(&attrs, it.ast_id.upcast());
1148 1157
1149 def = Some(DefData { 1158 def = Some(DefData {
1150 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } 1159 id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1151 .intern(self.def_collector.db) 1160 .intern(self.def_collector.db)
1152 .into(), 1161 .into(),
1153 name: &it.name, 1162 name: &it.name,
@@ -1164,7 +1173,7 @@ impl ModCollector<'_, '_> {
1164 self.collect_derives(&attrs, it.ast_id.upcast()); 1173 self.collect_derives(&attrs, it.ast_id.upcast());
1165 1174
1166 def = Some(DefData { 1175 def = Some(DefData {
1167 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } 1176 id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1168 .intern(self.def_collector.db) 1177 .intern(self.def_collector.db)
1169 .into(), 1178 .into(),
1170 name: &it.name, 1179 name: &it.name,
@@ -1178,7 +1187,7 @@ impl ModCollector<'_, '_> {
1178 if let Some(name) = &it.name { 1187 if let Some(name) = &it.name {
1179 def = Some(DefData { 1188 def = Some(DefData {
1180 id: ConstLoc { 1189 id: ConstLoc {
1181 container: container.into(), 1190 container: module.into(),
1182 id: ItemTreeId::new(self.file_id, id), 1191 id: ItemTreeId::new(self.file_id, id),
1183 } 1192 }
1184 .intern(self.def_collector.db) 1193 .intern(self.def_collector.db)
@@ -1193,7 +1202,7 @@ impl ModCollector<'_, '_> {
1193 let it = &self.item_tree[id]; 1202 let it = &self.item_tree[id];
1194 1203
1195 def = Some(DefData { 1204 def = Some(DefData {
1196 id: StaticLoc { container, id: ItemTreeId::new(self.file_id, id) } 1205 id: StaticLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1197 .intern(self.def_collector.db) 1206 .intern(self.def_collector.db)
1198 .into(), 1207 .into(),
1199 name: &it.name, 1208 name: &it.name,
@@ -1205,7 +1214,7 @@ impl ModCollector<'_, '_> {
1205 let it = &self.item_tree[id]; 1214 let it = &self.item_tree[id];
1206 1215
1207 def = Some(DefData { 1216 def = Some(DefData {
1208 id: TraitLoc { container, id: ItemTreeId::new(self.file_id, id) } 1217 id: TraitLoc { container: module, id: ItemTreeId::new(self.file_id, id) }
1209 .intern(self.def_collector.db) 1218 .intern(self.def_collector.db)
1210 .into(), 1219 .into(),
1211 name: &it.name, 1220 name: &it.name,
@@ -1218,7 +1227,7 @@ impl ModCollector<'_, '_> {
1218 1227
1219 def = Some(DefData { 1228 def = Some(DefData {
1220 id: TypeAliasLoc { 1229 id: TypeAliasLoc {
1221 container: container.into(), 1230 container: module.into(),
1222 id: ItemTreeId::new(self.file_id, id), 1231 id: ItemTreeId::new(self.file_id, id),
1223 } 1232 }
1224 .intern(self.def_collector.db) 1233 .intern(self.def_collector.db)
@@ -1446,8 +1455,11 @@ impl ModCollector<'_, '_> {
1446 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1455 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1447 1456
1448 // Case 1: try to resolve in legacy scope and expand macro_rules 1457 // Case 1: try to resolve in legacy scope and expand macro_rules
1449 if let Some(macro_call_id) = 1458 if let Ok(Ok(macro_call_id)) = macro_call_as_call_id(
1450 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1459 &ast_id,
1460 self.def_collector.db,
1461 self.def_collector.def_map.krate,
1462 |path| {
1451 path.as_ident().and_then(|name| { 1463 path.as_ident().and_then(|name| {
1452 self.def_collector.def_map.with_ancestor_maps( 1464 self.def_collector.def_map.with_ancestor_maps(
1453 self.def_collector.db, 1465 self.def_collector.db,
@@ -1455,8 +1467,9 @@ impl ModCollector<'_, '_> {
1455 &mut |map, module| map[module].scope.get_legacy_macro(&name), 1467 &mut |map, module| map[module].scope.get_legacy_macro(&name),
1456 ) 1468 )
1457 }) 1469 })
1458 }) 1470 },
1459 { 1471 &mut |_err| (),
1472 ) {
1460 self.def_collector.unexpanded_macros.push(MacroDirective { 1473 self.def_collector.unexpanded_macros.push(MacroDirective {
1461 module_id: self.module_id, 1474 module_id: self.module_id,
1462 ast_id, 1475 ast_id,
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs
index af3262439..d5de9899c 100644
--- a/crates/hir_def/src/nameres/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/mod_resolution.rs
@@ -2,7 +2,6 @@
2use base_db::{AnchoredPath, FileId}; 2use base_db::{AnchoredPath, FileId};
3use hir_expand::name::Name; 3use hir_expand::name::Name;
4use syntax::SmolStr; 4use syntax::SmolStr;
5use test_utils::mark;
6 5
7use crate::{db::DefDatabase, HirFileId}; 6use crate::{db::DefDatabase, HirFileId};
8 7
@@ -28,7 +27,7 @@ impl ModDir {
28 let depth = self.depth + 1; 27 let depth = self.depth + 1;
29 if depth > MOD_DEPTH_LIMIT { 28 if depth > MOD_DEPTH_LIMIT {
30 log::error!("MOD_DEPTH_LIMIT exceeded"); 29 log::error!("MOD_DEPTH_LIMIT exceeded");
31 mark::hit!(circular_mods); 30 cov_mark::hit!(circular_mods);
32 return None; 31 return None;
33 } 32 }
34 Some(ModDir { dir_path, root_non_dir_owner, depth }) 33 Some(ModDir { dir_path, root_non_dir_owner, depth })
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index fdcdc23ae..db459b1ed 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -13,7 +13,6 @@
13use base_db::Edition; 13use base_db::Edition;
14use hir_expand::name; 14use hir_expand::name;
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use test_utils::mark;
17 16
18use crate::{ 17use crate::{
19 db::DefDatabase, 18 db::DefDatabase,
@@ -63,7 +62,7 @@ impl ResolvePathResult {
63impl DefMap { 62impl DefMap {
64 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
65 if name == &name!(self) { 64 if name == &name!(self) {
66 mark::hit!(extern_crate_self_as); 65 cov_mark::hit!(extern_crate_self_as);
67 return PerNs::types(self.module_id(self.root).into(), Visibility::Public); 66 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
68 } 67 }
69 self.extern_prelude 68 self.extern_prelude
@@ -77,7 +76,7 @@ impl DefMap {
77 original_module: LocalModuleId, 76 original_module: LocalModuleId,
78 visibility: &RawVisibility, 77 visibility: &RawVisibility,
79 ) -> Option<Visibility> { 78 ) -> Option<Visibility> {
80 match visibility { 79 let mut vis = match visibility {
81 RawVisibility::Module(path) => { 80 RawVisibility::Module(path) => {
82 let (result, remaining) = 81 let (result, remaining) =
83 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); 82 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
@@ -86,15 +85,28 @@ impl DefMap {
86 } 85 }
87 let types = result.take_types()?; 86 let types = result.take_types()?;
88 match types { 87 match types {
89 ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), 88 ModuleDefId::ModuleId(m) => Visibility::Module(m),
90 _ => { 89 _ => {
91 // error: visibility needs to refer to module 90 // error: visibility needs to refer to module
92 None 91 return None;
93 } 92 }
94 } 93 }
95 } 94 }
96 RawVisibility::Public => Some(Visibility::Public), 95 RawVisibility::Public => Visibility::Public,
96 };
97
98 // In block expressions, `self` normally refers to the containing non-block module, and
99 // `super` to its parent (etc.). However, visibilities must only refer to a module in the
100 // DefMap they're written in, so we restrict them when that happens.
101 if let Visibility::Module(m) = vis {
102 if self.block_id() != m.block {
103 cov_mark::hit!(adjust_vis_in_block_def_map);
104 vis = Visibility::Module(self.module_id(self.root()));
105 log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
106 }
97 } 107 }
108
109 Some(vis)
98 } 110 }
99 111
100 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 112 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -144,7 +156,7 @@ impl DefMap {
144 } 156 }
145 } 157 }
146 158
147 pub(super) fn resolve_path_fp_with_macro_single( 159 fn resolve_path_fp_with_macro_single(
148 &self, 160 &self,
149 db: &dyn DefDatabase, 161 db: &dyn DefDatabase,
150 mode: ResolveMode, 162 mode: ResolveMode,
@@ -156,12 +168,12 @@ impl DefMap {
156 let mut curr_per_ns: PerNs = match path.kind { 168 let mut curr_per_ns: PerNs = match path.kind {
157 PathKind::DollarCrate(krate) => { 169 PathKind::DollarCrate(krate) => {
158 if krate == self.krate { 170 if krate == self.krate {
159 mark::hit!(macro_dollar_crate_self); 171 cov_mark::hit!(macro_dollar_crate_self);
160 PerNs::types(self.crate_root(db).into(), Visibility::Public) 172 PerNs::types(self.crate_root(db).into(), Visibility::Public)
161 } else { 173 } else {
162 let def_map = db.crate_def_map(krate); 174 let def_map = db.crate_def_map(krate);
163 let module = def_map.module_id(def_map.root); 175 let module = def_map.module_id(def_map.root);
164 mark::hit!(macro_dollar_crate_other); 176 cov_mark::hit!(macro_dollar_crate_other);
165 PerNs::types(module.into(), Visibility::Public) 177 PerNs::types(module.into(), Visibility::Public)
166 } 178 }
167 } 179 }
@@ -297,7 +309,7 @@ impl DefMap {
297 } 309 }
298 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 310 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
299 // enum variant 311 // enum variant
300 mark::hit!(can_import_enum_variant); 312 cov_mark::hit!(can_import_enum_variant);
301 let enum_data = db.enum_data(e); 313 let enum_data = db.enum_data(e);
302 match enum_data.variant(&segment) { 314 match enum_data.variant(&segment) {
303 Some(local_id) => { 315 Some(local_id) => {
@@ -372,10 +384,16 @@ impl DefMap {
372 } 384 }
373 } 385 }
374 }; 386 };
375 let from_extern_prelude = self 387 // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude
376 .extern_prelude 388 // from the crate DefMap.
377 .get(name) 389 let from_extern_prelude = match self.block {
378 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); 390 Some(_) => PerNs::none(),
391 None => self
392 .extern_prelude
393 .get(name)
394 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)),
395 };
396
379 let from_prelude = self.resolve_in_prelude(db, name); 397 let from_prelude = self.resolve_in_prelude(db, name);
380 398
381 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) 399 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index bd3e2701b..de3aa4f9a 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -9,7 +9,6 @@ use std::sync::Arc;
9 9
10use base_db::{fixture::WithFixture, SourceDatabase}; 10use base_db::{fixture::WithFixture, SourceDatabase};
11use expect_test::{expect, Expect}; 11use expect_test::{expect, Expect};
12use test_utils::mark;
13 12
14use crate::{db::DefDatabase, test_db::TestDB}; 13use crate::{db::DefDatabase, test_db::TestDB};
15 14
@@ -136,7 +135,7 @@ mod m {
136 135
137#[test] 136#[test]
138fn bogus_paths() { 137fn bogus_paths() {
139 mark::check!(bogus_paths); 138 cov_mark::check!(bogus_paths);
140 check( 139 check(
141 r#" 140 r#"
142//- /lib.rs 141//- /lib.rs
@@ -243,7 +242,7 @@ pub struct Baz;
243 242
244#[test] 243#[test]
245fn std_prelude() { 244fn std_prelude() {
246 mark::check!(std_prelude); 245 cov_mark::check!(std_prelude);
247 check( 246 check(
248 r#" 247 r#"
249//- /main.rs crate:main deps:test_crate 248//- /main.rs crate:main deps:test_crate
@@ -267,7 +266,7 @@ pub enum Foo { Bar, Baz };
267 266
268#[test] 267#[test]
269fn can_import_enum_variant() { 268fn can_import_enum_variant() {
270 mark::check!(can_import_enum_variant); 269 cov_mark::check!(can_import_enum_variant);
271 check( 270 check(
272 r#" 271 r#"
273enum E { V } 272enum E { V }
@@ -628,7 +627,7 @@ use crate::reex::*;
628 627
629#[test] 628#[test]
630fn underscore_pub_crate_reexport() { 629fn underscore_pub_crate_reexport() {
631 mark::check!(upgrade_underscore_visibility); 630 cov_mark::check!(upgrade_underscore_visibility);
632 check( 631 check(
633 r#" 632 r#"
634//- /main.rs crate:main deps:lib 633//- /main.rs crate:main deps:lib
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index e8e72e5ef..d5ef8ceb5 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -1,5 +1,4 @@
1use base_db::fixture::WithFixture; 1use base_db::fixture::WithFixture;
2use test_utils::mark;
3 2
4use crate::test_db::TestDB; 3use crate::test_db::TestDB;
5 4
@@ -63,7 +62,7 @@ fn unresolved_extern_crate() {
63 62
64#[test] 63#[test]
65fn extern_crate_self_as() { 64fn extern_crate_self_as() {
66 mark::check!(extern_crate_self_as); 65 cov_mark::check!(extern_crate_self_as);
67 check_diagnostics( 66 check_diagnostics(
68 r" 67 r"
69 //- /lib.rs 68 //- /lib.rs
@@ -140,7 +139,7 @@ fn inactive_item() {
140/// Tests that `cfg` attributes behind `cfg_attr` is handled properly. 139/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
141#[test] 140#[test]
142fn inactive_via_cfg_attr() { 141fn inactive_via_cfg_attr() {
143 mark::check!(cfg_attr_active); 142 cov_mark::check!(cfg_attr_active);
144 check_diagnostics( 143 check_diagnostics(
145 r#" 144 r#"
146 //- /lib.rs 145 //- /lib.rs
diff --git a/crates/hir_def/src/nameres/tests/globs.rs b/crates/hir_def/src/nameres/tests/globs.rs
index 2ae836e3c..17426d54d 100644
--- a/crates/hir_def/src/nameres/tests/globs.rs
+++ b/crates/hir_def/src/nameres/tests/globs.rs
@@ -148,7 +148,7 @@ pub(crate) struct PubCrateStruct;
148 148
149#[test] 149#[test]
150fn glob_across_crates() { 150fn glob_across_crates() {
151 mark::check!(glob_across_crates); 151 cov_mark::check!(glob_across_crates);
152 check( 152 check(
153 r#" 153 r#"
154//- /main.rs crate:main deps:test_crate 154//- /main.rs crate:main deps:test_crate
@@ -184,7 +184,7 @@ struct Foo;
184 184
185#[test] 185#[test]
186fn glob_enum() { 186fn glob_enum() {
187 mark::check!(glob_enum); 187 cov_mark::check!(glob_enum);
188 check( 188 check(
189 r#" 189 r#"
190enum Foo { Bar, Baz } 190enum Foo { Bar, Baz }
@@ -201,7 +201,7 @@ use self::Foo::*;
201 201
202#[test] 202#[test]
203fn glob_enum_group() { 203fn glob_enum_group() {
204 mark::check!(glob_enum_group); 204 cov_mark::check!(glob_enum_group);
205 check( 205 check(
206 r#" 206 r#"
207enum Foo { Bar, Baz } 207enum Foo { Bar, Baz }
@@ -218,7 +218,7 @@ use self::Foo::{*};
218 218
219#[test] 219#[test]
220fn glob_shadowed_def() { 220fn glob_shadowed_def() {
221 mark::check!(import_shadowed); 221 cov_mark::check!(import_shadowed);
222 check( 222 check(
223 r#" 223 r#"
224//- /lib.rs 224//- /lib.rs
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 36ed5e8ce..f65a655bf 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -210,7 +210,7 @@ macro_rules! bar {
210 210
211#[test] 211#[test]
212fn macro_rules_from_other_crates_are_visible_with_macro_use() { 212fn macro_rules_from_other_crates_are_visible_with_macro_use() {
213 mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use); 213 cov_mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
214 check( 214 check(
215 r#" 215 r#"
216//- /main.rs crate:main deps:foo 216//- /main.rs crate:main deps:foo
@@ -260,7 +260,7 @@ mod priv_mod {
260 260
261#[test] 261#[test]
262fn prelude_is_macro_use() { 262fn prelude_is_macro_use() {
263 mark::check!(prelude_is_macro_use); 263 cov_mark::check!(prelude_is_macro_use);
264 check( 264 check(
265 r#" 265 r#"
266//- /main.rs crate:main deps:foo 266//- /main.rs crate:main deps:foo
@@ -550,7 +550,7 @@ mod m {
550 550
551#[test] 551#[test]
552fn macro_dollar_crate_is_correct_in_item() { 552fn macro_dollar_crate_is_correct_in_item() {
553 mark::check!(macro_dollar_crate_self); 553 cov_mark::check!(macro_dollar_crate_self);
554 check( 554 check(
555 r#" 555 r#"
556//- /main.rs crate:main deps:foo 556//- /main.rs crate:main deps:foo
@@ -608,7 +608,7 @@ struct Baz;
608 608
609#[test] 609#[test]
610fn macro_dollar_crate_is_correct_in_indirect_deps() { 610fn macro_dollar_crate_is_correct_in_indirect_deps() {
611 mark::check!(macro_dollar_crate_other); 611 cov_mark::check!(macro_dollar_crate_other);
612 // From std 612 // From std
613 check( 613 check(
614 r#" 614 r#"
@@ -686,7 +686,7 @@ pub trait Clone {}
686 686
687#[test] 687#[test]
688fn macro_expansion_overflow() { 688fn macro_expansion_overflow() {
689 mark::check!(macro_expansion_overflow); 689 cov_mark::check!(macro_expansion_overflow);
690 check( 690 check(
691 r#" 691 r#"
692macro_rules! a { 692macro_rules! a {
diff --git a/crates/hir_def/src/nameres/tests/mod_resolution.rs b/crates/hir_def/src/nameres/tests/mod_resolution.rs
index e80b593aa..dfbbad1f9 100644
--- a/crates/hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/tests/mod_resolution.rs
@@ -2,7 +2,7 @@ use super::*;
2 2
3#[test] 3#[test]
4fn name_res_works_for_broken_modules() { 4fn name_res_works_for_broken_modules() {
5 mark::check!(name_res_works_for_broken_modules); 5 cov_mark::check!(name_res_works_for_broken_modules);
6 check( 6 check(
7 r" 7 r"
8//- /lib.rs 8//- /lib.rs
@@ -774,7 +774,7 @@ struct X;
774 774
775#[test] 775#[test]
776fn circular_mods() { 776fn circular_mods() {
777 mark::check!(circular_mods); 777 cov_mark::check!(circular_mods);
778 compute_crate_def_map( 778 compute_crate_def_map(
779 r#" 779 r#"
780//- /lib.rs 780//- /lib.rs
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index a469546c1..505493a74 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
101 break; 101 break;
102 } 102 }
103 ast::PathSegmentKind::SelfKw => { 103 ast::PathSegmentKind::SelfKw => {
104 kind = PathKind::Super(0); 104 // don't break out if `self` is the last segment of a path, this mean we got an
105 break; 105 // use tree like `foo::{self}` which we want to resolve as `foo`
106 if !segments.is_empty() {
107 kind = PathKind::Super(0);
108 break;
109 }
106 } 110 }
107 ast::PathSegmentKind::SuperKw => { 111 ast::PathSegmentKind::SuperKw => {
108 let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; 112 let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 };
@@ -117,6 +121,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
117 segments.reverse(); 121 segments.reverse();
118 generic_args.reverse(); 122 generic_args.reverse();
119 123
124 if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() {
125 // plain empty paths don't exist, this means we got a single `self` segment as our path
126 kind = PathKind::Super(0);
127 }
128
120 // handle local_inner_macros : 129 // handle local_inner_macros :
121 // Basically, even in rustc it is quite hacky: 130 // Basically, even in rustc it is quite hacky:
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 131 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
diff --git a/crates/hir_def/src/path/lower/lower_use.rs b/crates/hir_def/src/path/lower/lower_use.rs
index d584b0b70..e2965b033 100644
--- a/crates/hir_def/src/path/lower/lower_use.rs
+++ b/crates/hir_def/src/path/lower/lower_use.rs
@@ -6,7 +6,6 @@ use std::iter;
6use either::Either; 6use either::Either;
7use hir_expand::{hygiene::Hygiene, name::AsName}; 7use hir_expand::{hygiene::Hygiene, name::AsName};
8use syntax::ast::{self, NameOwner}; 8use syntax::ast::{self, NameOwner};
9use test_utils::mark;
10 9
11use crate::path::{ImportAlias, ModPath, PathKind}; 10use crate::path::{ImportAlias, ModPath, PathKind};
12 11
@@ -54,7 +53,7 @@ pub(crate) fn lower_use_tree(
54 // FIXME: report errors somewhere 53 // FIXME: report errors somewhere
55 // We get here if we do 54 // We get here if we do
56 } else if is_glob { 55 } else if is_glob {
57 mark::hit!(glob_enum_group); 56 cov_mark::hit!(glob_enum_group);
58 if let Some(prefix) = prefix { 57 if let Some(prefix) = prefix {
59 cb(prefix, &tree, is_glob, None) 58 cb(prefix, &tree, is_glob, None)
60 } 59 }
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index e85f85e49..42736171e 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -19,10 +19,10 @@ use crate::{
19 path::{ModPath, PathKind}, 19 path::{ModPath, PathKind},
20 per_ns::PerNs, 20 per_ns::PerNs,
21 visibility::{RawVisibility, Visibility}, 21 visibility::{RawVisibility, Visibility},
22 AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, 22 AdtId, AssocContainerId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
23 EnumVariantId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, 23 FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, LocalModuleId,
24 LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 24 Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
25 TypeParamId, VariantId, 25 VariantId,
26}; 26};
27 27
28#[derive(Debug, Clone, Default)] 28#[derive(Debug, Clone, Default)]
@@ -34,7 +34,7 @@ pub struct Resolver {
34// FIXME how to store these best 34// FIXME how to store these best
35#[derive(Debug, Clone)] 35#[derive(Debug, Clone)]
36struct ModuleItemMap { 36struct ModuleItemMap {
37 crate_def_map: Arc<DefMap>, 37 def_map: Arc<DefMap>,
38 module_id: LocalModuleId, 38 module_id: LocalModuleId,
39} 39}
40 40
@@ -337,11 +337,21 @@ impl Resolver {
337 let mut traits = FxHashSet::default(); 337 let mut traits = FxHashSet::default();
338 for scope in &self.scopes { 338 for scope in &self.scopes {
339 if let Scope::ModuleScope(m) = scope { 339 if let Scope::ModuleScope(m) = scope {
340 if let Some(prelude) = m.crate_def_map.prelude() { 340 if let Some(prelude) = m.def_map.prelude() {
341 let prelude_def_map = prelude.def_map(db); 341 let prelude_def_map = prelude.def_map(db);
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.crate_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
@@ -349,7 +359,7 @@ impl Resolver {
349 359
350 fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> { 360 fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> {
351 self.scopes.iter().rev().find_map(|scope| match scope { 361 self.scopes.iter().rev().find_map(|scope| match scope {
352 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 362 Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)),
353 363
354 _ => None, 364 _ => None,
355 }) 365 })
@@ -413,21 +423,21 @@ impl Scope {
413 // def: m.module.into(), 423 // def: m.module.into(),
414 // }), 424 // }),
415 // ); 425 // );
416 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, def)| { 426 m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
417 f(name.clone(), ScopeDef::PerNs(def)); 427 f(name.clone(), ScopeDef::PerNs(def));
418 }); 428 });
419 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 429 m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
420 let scope = PerNs::macros(macro_, Visibility::Public); 430 let scope = PerNs::macros(macro_, Visibility::Public);
421 seen.insert((name.clone(), scope)); 431 seen.insert((name.clone(), scope));
422 f(name.clone(), ScopeDef::PerNs(scope)); 432 f(name.clone(), ScopeDef::PerNs(scope));
423 }); 433 });
424 m.crate_def_map.extern_prelude().for_each(|(name, &def)| { 434 m.def_map.extern_prelude().for_each(|(name, &def)| {
425 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); 435 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
426 }); 436 });
427 BUILTIN_SCOPE.iter().for_each(|(name, &def)| { 437 BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
428 f(name.clone(), ScopeDef::PerNs(def)); 438 f(name.clone(), ScopeDef::PerNs(def));
429 }); 439 });
430 if let Some(prelude) = m.crate_def_map.prelude() { 440 if let Some(prelude) = m.def_map.prelude() {
431 let prelude_def_map = prelude.def_map(db); 441 let prelude_def_map = prelude.def_map(db);
432 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { 442 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
433 let seen_tuple = (name.clone(), def); 443 let seen_tuple = (name.clone(), def);
@@ -513,8 +523,8 @@ impl Resolver {
513 self.push_scope(Scope::ImplDefScope(impl_def)) 523 self.push_scope(Scope::ImplDefScope(impl_def))
514 } 524 }
515 525
516 fn push_module_scope(self, crate_def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver { 526 fn push_module_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
517 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 527 self.push_scope(Scope::ModuleScope(ModuleItemMap { def_map, module_id }))
518 } 528 }
519 529
520 fn push_expr_scope( 530 fn push_expr_scope(
@@ -534,7 +544,7 @@ impl ModuleItemMap {
534 path: &ModPath, 544 path: &ModPath,
535 ) -> Option<ResolveValueResult> { 545 ) -> Option<ResolveValueResult> {
536 let (module_def, idx) = 546 let (module_def, idx) =
537 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); 547 self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
538 match idx { 548 match idx {
539 None => { 549 None => {
540 let value = to_value_ns(module_def)?; 550 let value = to_value_ns(module_def)?;
@@ -564,7 +574,7 @@ impl ModuleItemMap {
564 path: &ModPath, 574 path: &ModPath,
565 ) -> Option<(TypeNs, Option<usize>)> { 575 ) -> Option<(TypeNs, Option<usize>)> {
566 let (module_def, idx) = 576 let (module_def, idx) =
567 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); 577 self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
568 let res = to_type_ns(module_def)?; 578 let res = to_type_ns(module_def)?;
569 Some((res, idx)) 579 Some((res, idx))
570 } 580 }
@@ -678,19 +688,10 @@ impl HasResolver for DefWithBodyId {
678 } 688 }
679} 689}
680 690
681impl HasResolver for ContainerId {
682 fn resolver(self, db: &dyn DefDatabase) -> Resolver {
683 match self {
684 ContainerId::ModuleId(it) => it.resolver(db),
685 ContainerId::DefWithBodyId(it) => it.module(db).resolver(db),
686 }
687 }
688}
689
690impl HasResolver for AssocContainerId { 691impl HasResolver for AssocContainerId {
691 fn resolver(self, db: &dyn DefDatabase) -> Resolver { 692 fn resolver(self, db: &dyn DefDatabase) -> Resolver {
692 match self { 693 match self {
693 AssocContainerId::ContainerId(it) => it.resolver(db), 694 AssocContainerId::ModuleId(it) => it.resolver(db),
694 AssocContainerId::TraitId(it) => it.resolver(db), 695 AssocContainerId::TraitId(it) => it.resolver(db),
695 AssocContainerId::ImplId(it) => it.resolver(db), 696 AssocContainerId::ImplId(it) => it.resolver(db),
696 } 697 }
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index eda982c85..10977761c 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet;
15use syntax::{algo, ast, AstNode, TextRange, TextSize}; 15use syntax::{algo, ast, AstNode, TextRange, TextSize};
16use test_utils::extract_annotations; 16use test_utils::extract_annotations;
17 17
18use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; 18use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId};
19 19
20#[salsa::database( 20#[salsa::database(
21 base_db::SourceDatabaseExtStorage, 21 base_db::SourceDatabaseExtStorage,
@@ -115,14 +115,9 @@ impl TestDB {
115 if file_id != position.file_id.into() { 115 if file_id != position.file_id.into() {
116 continue; 116 continue;
117 } 117 }
118 let root = self.parse_or_expand(file_id).unwrap();
119 let ast_map = self.ast_id_map(file_id);
120 let item_tree = self.item_tree(file_id);
121 for decl in module.scope.declarations() { 118 for decl in module.scope.declarations() {
122 if let ModuleDefId::FunctionId(it) = decl { 119 if let ModuleDefId::FunctionId(it) = decl {
123 let ast = 120 let range = it.lookup(self).source(self).value.syntax().text_range();
124 ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root);
125 let range = ast.syntax().text_range();
126 121
127 if !range.contains(position.offset) { 122 if !range.contains(position.offset) {
128 continue; 123 continue;