diff options
Diffstat (limited to 'crates/hir_def/src')
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 | }; |
27 | use cfg::CfgOptions; | 26 | use cfg::CfgOptions; |
28 | 27 | ||
@@ -92,10 +91,10 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | |||
92 | impl StructData { | 91 | impl 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 { | |||
126 | impl EnumData { | 125 | impl 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 | }; |
16 | use test_utils::mark; | ||
17 | use tt::Subtree; | 16 | use tt::Subtree; |
18 | 17 | ||
19 | use crate::{ | 18 | use 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}; | |||
20 | use profile::Count; | 20 | use profile::Count; |
21 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
22 | use syntax::{ast, AstNode, AstPtr}; | 22 | use syntax::{ast, AstNode, AstPtr}; |
23 | use test_utils::mark; | ||
24 | 23 | ||
25 | pub(crate) use lower::LowerCtx; | 24 | pub(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 | ||
4 | use std::{any::type_name, mem, sync::Arc}; | 4 | use std::mem; |
5 | 5 | ||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{ | 7 | use 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 | }; |
12 | use la_arena::Arena; | 12 | use la_arena::Arena; |
13 | use profile::Count; | 13 | use profile::Count; |
14 | use rustc_hash::FxHashMap; | ||
15 | use syntax::{ | 14 | use 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 | }; |
22 | use test_utils::mark; | ||
23 | 21 | ||
24 | use crate::{ | 22 | use 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 | ||
43 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; | 39 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; |
@@ -61,15 +57,12 @@ impl LowerCtx { | |||
61 | 57 | ||
62 | pub(super) fn lower( | 58 | pub(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 | ||
93 | struct ExprCollector<'a> { | 81 | struct 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 | ||
103 | impl ExprCollector<'_> { | 88 | impl 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#" |
460 | fn test() { | 460 | fn 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 | ||
3 | use base_db::{fixture::WithFixture, SourceDatabase}; | 3 | use base_db::{fixture::WithFixture, SourceDatabase}; |
4 | use expect_test::Expect; | 4 | use expect_test::Expect; |
5 | use test_utils::mark; | ||
6 | 5 | ||
7 | use crate::{test_db::TestDB, ModuleDefId}; | 6 | use 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] |
50 | fn your_stack_belongs_to_me() { | 49 | fn 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 | " |
54 | macro_rules! n_nuple { | 53 | macro_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 |
168 | use core::mark; | 168 | use core::cov_mark; |
169 | 169 | ||
170 | fn f() { | 170 | fn 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 |
177 | pub mod mark { | 177 | pub 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] | ||
264 | fn 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#" | ||
270 | mod 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 @@ | |||
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use hir_expand::name::{name, AsName, Name}; | 8 | use 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)] |
11 | pub enum Signedness { | 11 | pub 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, |
17 | pub 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)] | ||
27 | pub enum FloatBitness { | ||
28 | X32, | ||
29 | X64, | ||
30 | } | 18 | } |
31 | 19 | ||
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 20 | /// Different unsigned int types. |
33 | pub struct BuiltinInt { | 21 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
34 | pub signedness: Signedness, | 22 | pub 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)] |
39 | pub struct BuiltinFloat { | 32 | pub 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] |
115 | impl BuiltinInt { | 111 | impl 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] | ||
128 | impl 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] |
154 | impl BuiltinFloat { | 145 | impl 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 | ||
19 | pub trait ChildBySource { | 19 | pub trait ChildBySource { |
20 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap; | ||
21 | } | ||
22 | |||
23 | impl 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 | ||
28 | impl 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 | ||
49 | impl ChildBySource for ImplId { | 50 | impl 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 | ||
75 | impl ChildBySource for ModuleId { | 72 | impl 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 | ||
83 | impl ChildBySource for ItemScope { | 80 | impl 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 | ||
136 | impl ChildBySource for VariantId { | 131 | impl 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 | ||
157 | impl ChildBySource for EnumId { | 149 | impl 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 | ||
172 | impl ChildBySource for DefWithBodyId { | 160 | impl 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 | ||
136 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<DefMap> { | 136 | fn 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)] | ||
103 | pub struct UnresolvedMacroCall { | ||
104 | pub file: HirFileId, | ||
105 | pub node: AstPtr<ast::MacroCall>, | ||
106 | } | ||
107 | |||
108 | impl 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}; | |||
17 | use syntax::ast::RangeOp; | 17 | use syntax::ast::RangeOp; |
18 | 18 | ||
19 | use crate::{ | 19 | use 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 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
4 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | ||
6 | 7 | ||
7 | use crate::nameres::DefMap; | 8 | use crate::nameres::DefMap; |
8 | use crate::{ | 9 | use 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( | |||
245 | fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { | 251 | fn 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 | ||
423 | impl ChildBySource for GenericDefId { | 423 | impl 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; | |||
8 | use indexmap::{map::Entry, IndexMap}; | 8 | use indexmap::{map::Entry, IndexMap}; |
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use rustc_hash::{FxHashSet, FxHasher}; | 10 | use rustc_hash::{FxHashSet, FxHasher}; |
11 | use test_utils::mark; | ||
12 | 11 | ||
13 | use crate::{ | 12 | use 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> { | |||
462 | mod tests { | 462 | mod 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; | |||
9 | use once_cell::sync::Lazy; | 9 | use once_cell::sync::Lazy; |
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use stdx::format_to; | 11 | use stdx::format_to; |
12 | use test_utils::mark; | ||
13 | 12 | ||
14 | use crate::{ | 13 | use 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; | |||
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | use test_utils::mark; | ||
29 | 28 | ||
30 | use crate::{ | 29 | use 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 | ||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 59 | use 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 | }; |
63 | use la_arena::Idx; | 65 | use la_arena::Idx; |
64 | use nameres::DefMap; | 66 | use 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)] |
104 | pub struct ItemLoc<N: ItemTreeNode> { | 110 | pub 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 { | |||
273 | pub type LocalConstParamId = Idx<generics::ConstParamData>; | 279 | pub type LocalConstParamId = Idx<generics::ConstParamData>; |
274 | 280 | ||
275 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 281 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
276 | pub enum ContainerId { | ||
277 | ModuleId(ModuleId), | ||
278 | DefWithBodyId(DefWithBodyId), | ||
279 | } | ||
280 | |||
281 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
282 | pub enum AssocContainerId { | 282 | pub enum AssocContainerId { |
283 | ContainerId(ContainerId), | 283 | ModuleId(ModuleId), |
284 | ImplId(ImplId), | 284 | ImplId(ImplId), |
285 | TraitId(TraitId), | 285 | TraitId(TraitId), |
286 | } | 286 | } |
287 | impl_from!(ContainerId for AssocContainerId); | 287 | impl_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 | ||
444 | impl 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 | |||
453 | impl HasModule for AssocContainerId { | 444 | impl 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 | ||
480 | impl HasModule for VariantId { | 470 | impl 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 | ||
524 | impl HasModule for StaticLoc { | 514 | impl 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 | |||
520 | impl 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 | ||
613 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | 629 | struct UnresolvedMacro; |
614 | fn as_call_id_with_errors( | 630 | |
615 | &self, | 631 | fn 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 | ||
648 | impl AsMacroCall for AstIdWithPath<ast::Item> { | 659 | fn 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 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
20 | use syntax::ast; | 20 | use syntax::ast; |
21 | use test_utils::mark; | ||
22 | use tt::{Leaf, TokenTree}; | 21 | use tt::{Leaf, TokenTree}; |
23 | 22 | ||
24 | use crate::{ | 23 | use 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 | ||
44 | const GLOB_RECURSION_LIMIT: usize = 100; | 45 | const 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 @@ | |||
2 | use base_db::{AnchoredPath, FileId}; | 2 | use base_db::{AnchoredPath, FileId}; |
3 | use hir_expand::name::Name; | 3 | use hir_expand::name::Name; |
4 | use syntax::SmolStr; | 4 | use syntax::SmolStr; |
5 | use test_utils::mark; | ||
6 | 5 | ||
7 | use crate::{db::DefDatabase, HirFileId}; | 6 | use 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 @@ | |||
13 | use base_db::Edition; | 13 | use base_db::Edition; |
14 | use hir_expand::name; | 14 | use hir_expand::name; |
15 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
16 | use test_utils::mark; | ||
17 | 16 | ||
18 | use crate::{ | 17 | use crate::{ |
19 | db::DefDatabase, | 18 | db::DefDatabase, |
@@ -63,7 +62,7 @@ impl ResolvePathResult { | |||
63 | impl DefMap { | 62 | impl 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 | ||
10 | use base_db::{fixture::WithFixture, SourceDatabase}; | 10 | use base_db::{fixture::WithFixture, SourceDatabase}; |
11 | use expect_test::{expect, Expect}; | 11 | use expect_test::{expect, Expect}; |
12 | use test_utils::mark; | ||
13 | 12 | ||
14 | use crate::{db::DefDatabase, test_db::TestDB}; | 13 | use crate::{db::DefDatabase, test_db::TestDB}; |
15 | 14 | ||
@@ -136,7 +135,7 @@ mod m { | |||
136 | 135 | ||
137 | #[test] | 136 | #[test] |
138 | fn bogus_paths() { | 137 | fn 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] |
245 | fn std_prelude() { | 244 | fn 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] |
269 | fn can_import_enum_variant() { | 268 | fn 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#" |
273 | enum E { V } | 272 | enum E { V } |
@@ -628,7 +627,7 @@ use crate::reex::*; | |||
628 | 627 | ||
629 | #[test] | 628 | #[test] |
630 | fn underscore_pub_crate_reexport() { | 629 | fn 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 @@ | |||
1 | use base_db::fixture::WithFixture; | 1 | use base_db::fixture::WithFixture; |
2 | use test_utils::mark; | ||
3 | 2 | ||
4 | use crate::test_db::TestDB; | 3 | use crate::test_db::TestDB; |
5 | 4 | ||
@@ -63,7 +62,7 @@ fn unresolved_extern_crate() { | |||
63 | 62 | ||
64 | #[test] | 63 | #[test] |
65 | fn extern_crate_self_as() { | 64 | fn 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] |
142 | fn inactive_via_cfg_attr() { | 141 | fn 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] |
150 | fn glob_across_crates() { | 150 | fn 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] |
186 | fn glob_enum() { | 186 | fn glob_enum() { |
187 | mark::check!(glob_enum); | 187 | cov_mark::check!(glob_enum); |
188 | check( | 188 | check( |
189 | r#" | 189 | r#" |
190 | enum Foo { Bar, Baz } | 190 | enum Foo { Bar, Baz } |
@@ -201,7 +201,7 @@ use self::Foo::*; | |||
201 | 201 | ||
202 | #[test] | 202 | #[test] |
203 | fn glob_enum_group() { | 203 | fn glob_enum_group() { |
204 | mark::check!(glob_enum_group); | 204 | cov_mark::check!(glob_enum_group); |
205 | check( | 205 | check( |
206 | r#" | 206 | r#" |
207 | enum Foo { Bar, Baz } | 207 | enum Foo { Bar, Baz } |
@@ -218,7 +218,7 @@ use self::Foo::{*}; | |||
218 | 218 | ||
219 | #[test] | 219 | #[test] |
220 | fn glob_shadowed_def() { | 220 | fn 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] |
212 | fn macro_rules_from_other_crates_are_visible_with_macro_use() { | 212 | fn 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] |
262 | fn prelude_is_macro_use() { | 262 | fn 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] |
552 | fn macro_dollar_crate_is_correct_in_item() { | 552 | fn 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] |
610 | fn macro_dollar_crate_is_correct_in_indirect_deps() { | 610 | fn 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] |
688 | fn macro_expansion_overflow() { | 688 | fn macro_expansion_overflow() { |
689 | mark::check!(macro_expansion_overflow); | 689 | cov_mark::check!(macro_expansion_overflow); |
690 | check( | 690 | check( |
691 | r#" | 691 | r#" |
692 | macro_rules! a { | 692 | macro_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] |
4 | fn name_res_works_for_broken_modules() { | 4 | fn 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] |
776 | fn circular_mods() { | 776 | fn 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; | |||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{hygiene::Hygiene, name::AsName}; | 7 | use hir_expand::{hygiene::Hygiene, name::AsName}; |
8 | use syntax::ast::{self, NameOwner}; | 8 | use syntax::ast::{self, NameOwner}; |
9 | use test_utils::mark; | ||
10 | 9 | ||
11 | use crate::path::{ImportAlias, ModPath, PathKind}; | 10 | use 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)] |
36 | struct ModuleItemMap { | 36 | struct 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 | ||
681 | impl 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 | |||
690 | impl HasResolver for AssocContainerId { | 691 | impl 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; | |||
15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; | 15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; |
16 | use test_utils::extract_annotations; | 16 | use test_utils::extract_annotations; |
17 | 17 | ||
18 | use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; | 18 | use 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; |