diff options
Diffstat (limited to 'crates/hir_def')
32 files changed, 1896 insertions, 702 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index 06f0b9b18..ed36c3109 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs | |||
@@ -351,7 +351,7 @@ fn lower_field( | |||
351 | ) -> FieldData { | 351 | ) -> FieldData { |
352 | FieldData { | 352 | FieldData { |
353 | name: field.name.clone(), | 353 | name: field.name.clone(), |
354 | type_ref: field.type_ref.clone(), | 354 | type_ref: item_tree[field.type_ref].clone(), |
355 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), | 355 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), |
356 | } | 356 | } |
357 | } | 357 | } |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 1b09ff816..fe4c3fa28 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -196,17 +196,26 @@ impl Attrs { | |||
196 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | 196 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { |
197 | let raw_attrs = match def { | 197 | let raw_attrs = match def { |
198 | AttrDefId::ModuleId(module) => { | 198 | AttrDefId::ModuleId(module) => { |
199 | let def_map = db.crate_def_map(module.krate); | 199 | let def_map = module.def_map(db); |
200 | let mod_data = &def_map[module.local_id]; | 200 | let mod_data = &def_map[module.local_id]; |
201 | match mod_data.declaration_source(db) { | 201 | match mod_data.declaration_source(db) { |
202 | Some(it) => { | 202 | Some(it) => { |
203 | RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) | 203 | let raw_attrs = RawAttrs::from_attrs_owner( |
204 | db, | ||
205 | it.as_ref().map(|it| it as &dyn AttrsOwner), | ||
206 | ); | ||
207 | match mod_data.definition_source(db) { | ||
208 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
209 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
210 | _ => raw_attrs, | ||
211 | } | ||
204 | } | 212 | } |
205 | None => RawAttrs::from_attrs_owner( | 213 | None => RawAttrs::from_attrs_owner( |
206 | db, | 214 | db, |
207 | mod_data.definition_source(db).as_ref().map(|src| match src { | 215 | mod_data.definition_source(db).as_ref().map(|src| match src { |
208 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, | 216 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, |
209 | ModuleSource::Module(module) => module as &dyn AttrsOwner, | 217 | ModuleSource::Module(module) => module as &dyn AttrsOwner, |
218 | ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner, | ||
210 | }), | 219 | }), |
211 | ), | 220 | ), |
212 | } | 221 | } |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 344f0b6c0..ff4b4a0cf 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -17,6 +17,7 @@ use hir_expand::{ | |||
17 | HirFileId, InFile, MacroDefId, | 17 | HirFileId, InFile, MacroDefId, |
18 | }; | 18 | }; |
19 | use la_arena::{Arena, ArenaMap}; | 19 | use la_arena::{Arena, ArenaMap}; |
20 | use profile::Count; | ||
20 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
21 | use syntax::{ast, AstNode, AstPtr}; | 22 | use syntax::{ast, AstNode, AstPtr}; |
22 | use test_utils::mark; | 23 | use test_utils::mark; |
@@ -29,10 +30,10 @@ use crate::{ | |||
29 | expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, | 30 | expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, |
30 | item_scope::BuiltinShadowMode, | 31 | item_scope::BuiltinShadowMode, |
31 | item_scope::ItemScope, | 32 | item_scope::ItemScope, |
32 | nameres::CrateDefMap, | 33 | nameres::DefMap, |
33 | path::{ModPath, Path}, | 34 | path::{ModPath, Path}, |
34 | src::HasSource, | 35 | src::HasSource, |
35 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 36 | AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, |
36 | }; | 37 | }; |
37 | 38 | ||
38 | /// A subset of Expander that only deals with cfg attributes. We only need it to | 39 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
@@ -45,10 +46,10 @@ pub(crate) struct CfgExpander { | |||
45 | 46 | ||
46 | pub(crate) struct Expander { | 47 | pub(crate) struct Expander { |
47 | cfg_expander: CfgExpander, | 48 | cfg_expander: CfgExpander, |
48 | crate_def_map: Arc<CrateDefMap>, | 49 | def_map: Arc<DefMap>, |
49 | current_file_id: HirFileId, | 50 | current_file_id: HirFileId, |
50 | ast_id_map: Arc<AstIdMap>, | 51 | ast_id_map: Arc<AstIdMap>, |
51 | module: ModuleId, | 52 | module: LocalModuleId, |
52 | recursion_limit: usize, | 53 | recursion_limit: usize, |
53 | } | 54 | } |
54 | 55 | ||
@@ -86,14 +87,14 @@ impl Expander { | |||
86 | module: ModuleId, | 87 | module: ModuleId, |
87 | ) -> Expander { | 88 | ) -> Expander { |
88 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); | 89 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); |
89 | let crate_def_map = db.crate_def_map(module.krate); | 90 | let crate_def_map = module.def_map(db); |
90 | let ast_id_map = db.ast_id_map(current_file_id); | 91 | let ast_id_map = db.ast_id_map(current_file_id); |
91 | Expander { | 92 | Expander { |
92 | cfg_expander, | 93 | cfg_expander, |
93 | crate_def_map, | 94 | def_map: crate_def_map, |
94 | current_file_id, | 95 | current_file_id, |
95 | ast_id_map, | 96 | ast_id_map, |
96 | module, | 97 | module: module.local_id, |
97 | recursion_limit: 0, | 98 | recursion_limit: 0, |
98 | } | 99 | } |
99 | } | 100 | } |
@@ -101,7 +102,6 @@ impl Expander { | |||
101 | pub(crate) fn enter_expand<T: ast::AstNode>( | 102 | pub(crate) fn enter_expand<T: ast::AstNode>( |
102 | &mut self, | 103 | &mut self, |
103 | db: &dyn DefDatabase, | 104 | db: &dyn DefDatabase, |
104 | local_scope: Option<&ItemScope>, | ||
105 | macro_call: ast::MacroCall, | 105 | macro_call: ast::MacroCall, |
106 | ) -> ExpandResult<Option<(Mark, T)>> { | 106 | ) -> ExpandResult<Option<(Mark, T)>> { |
107 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { | 107 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { |
@@ -111,25 +111,19 @@ impl Expander { | |||
111 | 111 | ||
112 | let macro_call = InFile::new(self.current_file_id, ¯o_call); | 112 | let macro_call = InFile::new(self.current_file_id, ¯o_call); |
113 | 113 | ||
114 | let resolver = |path: ModPath| -> Option<MacroDefId> { | 114 | let resolver = |
115 | if let Some(local_scope) = local_scope { | 115 | |path: ModPath| -> Option<MacroDefId> { self.resolve_path_as_macro(db, &path) }; |
116 | if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) { | ||
117 | return Some(def); | ||
118 | } | ||
119 | } | ||
120 | self.resolve_path_as_macro(db, &path) | ||
121 | }; | ||
122 | 116 | ||
123 | let mut err = None; | 117 | let mut err = None; |
124 | let call_id = | 118 | let call_id = |
125 | macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| { | 119 | macro_call.as_call_id_with_errors(db, self.def_map.krate(), resolver, &mut |e| { |
126 | err.get_or_insert(e); | 120 | err.get_or_insert(e); |
127 | }); | 121 | }); |
128 | let call_id = match call_id { | 122 | let call_id = match call_id { |
129 | Some(it) => it, | 123 | Some(it) => it, |
130 | None => { | 124 | None => { |
131 | if err.is_none() { | 125 | if err.is_none() { |
132 | eprintln!("no error despite `as_call_id_with_errors` returning `None`"); | 126 | log::warn!("no error despite `as_call_id_with_errors` returning `None`"); |
133 | } | 127 | } |
134 | return ExpandResult { value: None, err }; | 128 | return ExpandResult { value: None, err }; |
135 | } | 129 | } |
@@ -203,10 +197,7 @@ impl Expander { | |||
203 | } | 197 | } |
204 | 198 | ||
205 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 199 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
206 | self.crate_def_map | 200 | self.def_map.resolve_path(db, self.module, path, BuiltinShadowMode::Other).0.take_macros() |
207 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) | ||
208 | .0 | ||
209 | .take_macros() | ||
210 | } | 201 | } |
211 | 202 | ||
212 | fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> { | 203 | fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> { |
@@ -237,6 +228,7 @@ pub struct Body { | |||
237 | /// The `ExprId` of the actual body expression. | 228 | /// The `ExprId` of the actual body expression. |
238 | pub body_expr: ExprId, | 229 | pub body_expr: ExprId, |
239 | pub item_scope: ItemScope, | 230 | pub item_scope: ItemScope, |
231 | _c: Count<Self>, | ||
240 | } | 232 | } |
241 | 233 | ||
242 | pub type ExprPtr = AstPtr<ast::Expr>; | 234 | pub type ExprPtr = AstPtr<ast::Expr>; |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 4ce5e5b72..40beb2f7a 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -1,7 +1,7 @@ | |||
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, sync::Arc}; | 4 | use std::{any::type_name, mem, sync::Arc}; |
5 | 5 | ||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{ | 7 | use hir_expand::{ |
@@ -10,6 +10,7 @@ use hir_expand::{ | |||
10 | ExpandError, HirFileId, MacroDefId, MacroDefKind, | 10 | ExpandError, HirFileId, MacroDefId, MacroDefKind, |
11 | }; | 11 | }; |
12 | use la_arena::Arena; | 12 | use la_arena::Arena; |
13 | use profile::Count; | ||
13 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
14 | use syntax::{ | 15 | use syntax::{ |
15 | ast::{ | 16 | ast::{ |
@@ -23,7 +24,7 @@ use test_utils::mark; | |||
23 | use crate::{ | 24 | use crate::{ |
24 | adt::StructKind, | 25 | adt::StructKind, |
25 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, | 26 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, |
26 | builtin_type::{BuiltinFloat, BuiltinInt}, | 27 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
27 | db::DefDatabase, | 28 | db::DefDatabase, |
28 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, | 29 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, |
29 | expr::{ | 30 | expr::{ |
@@ -35,8 +36,8 @@ use crate::{ | |||
35 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, | 36 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, |
36 | path::{GenericArgs, Path}, | 37 | path::{GenericArgs, Path}, |
37 | type_ref::{Mutability, Rawness, TypeRef}, | 38 | type_ref::{Mutability, Rawness, TypeRef}, |
38 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 39 | AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, |
39 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 40 | ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
40 | }; | 41 | }; |
41 | 42 | ||
42 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; | 43 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; |
@@ -77,6 +78,7 @@ pub(super) fn lower( | |||
77 | params: Vec::new(), | 78 | params: Vec::new(), |
78 | body_expr: dummy_expr_id(), | 79 | body_expr: dummy_expr_id(), |
79 | item_scope: Default::default(), | 80 | item_scope: Default::default(), |
81 | _c: Count::new(), | ||
80 | }, | 82 | }, |
81 | item_trees: { | 83 | item_trees: { |
82 | let mut map = FxHashMap::default(); | 84 | let mut map = FxHashMap::default(); |
@@ -150,8 +152,8 @@ impl ExprCollector<'_> { | |||
150 | fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { | 152 | fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { |
151 | self.make_expr(expr, Err(SyntheticSyntax)) | 153 | self.make_expr(expr, Err(SyntheticSyntax)) |
152 | } | 154 | } |
153 | fn empty_block(&mut self) -> ExprId { | 155 | fn unit(&mut self) -> ExprId { |
154 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None }) | 156 | self.alloc_expr_desugared(Expr::Tuple { exprs: Vec::new() }) |
155 | } | 157 | } |
156 | fn missing_expr(&mut self) -> ExprId { | 158 | fn missing_expr(&mut self) -> ExprId { |
157 | self.alloc_expr_desugared(Expr::Missing) | 159 | self.alloc_expr_desugared(Expr::Missing) |
@@ -220,7 +222,7 @@ impl ExprCollector<'_> { | |||
220 | MatchArm { pat, expr: then_branch, guard: None }, | 222 | MatchArm { pat, expr: then_branch, guard: None }, |
221 | MatchArm { | 223 | MatchArm { |
222 | pat: placeholder_pat, | 224 | pat: placeholder_pat, |
223 | expr: else_branch.unwrap_or_else(|| self.empty_block()), | 225 | expr: else_branch.unwrap_or_else(|| self.unit()), |
224 | guard: None, | 226 | guard: None, |
225 | }, | 227 | }, |
226 | ]; | 228 | ]; |
@@ -559,7 +561,7 @@ impl ExprCollector<'_> { | |||
559 | let outer_file = self.expander.current_file_id; | 561 | let outer_file = self.expander.current_file_id; |
560 | 562 | ||
561 | let macro_call = self.expander.to_source(AstPtr::new(&e)); | 563 | let macro_call = self.expander.to_source(AstPtr::new(&e)); |
562 | let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e); | 564 | let res = self.expander.enter_expand(self.db, e); |
563 | 565 | ||
564 | match &res.err { | 566 | match &res.err { |
565 | Some(ExpandError::UnresolvedProcMacro) => { | 567 | Some(ExpandError::UnresolvedProcMacro) => { |
@@ -695,12 +697,30 @@ impl ExprCollector<'_> { | |||
695 | } | 697 | } |
696 | 698 | ||
697 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { | 699 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
698 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); | 700 | let ast_id = self.expander.ast_id(&block); |
701 | let block_loc = | ||
702 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | ||
703 | let block_id = self.db.intern_block(block_loc); | ||
704 | let opt_def_map = self.db.block_def_map(block_id); | ||
705 | let has_def_map = opt_def_map.is_some(); | ||
706 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | ||
707 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | ||
708 | 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); | ||
710 | |||
699 | self.collect_stmts_items(block.statements()); | 711 | self.collect_stmts_items(block.statements()); |
700 | let statements = | 712 | let statements = |
701 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | 713 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); |
702 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 714 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
703 | self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) | 715 | let syntax_node_ptr = AstPtr::new(&block.into()); |
716 | let expr_id = self.alloc_expr( | ||
717 | Expr::Block { id: block_id, statements, tail, label: None }, | ||
718 | syntax_node_ptr, | ||
719 | ); | ||
720 | |||
721 | self.expander.def_map = prev_def_map; | ||
722 | self.expander.module = prev_local_module; | ||
723 | expr_id | ||
704 | } | 724 | } |
705 | 725 | ||
706 | fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) { | 726 | fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) { |
@@ -792,7 +812,7 @@ impl ExprCollector<'_> { | |||
792 | } | 812 | } |
793 | Either::Right(e) => { | 813 | Either::Right(e) => { |
794 | let mac = MacroDefId { | 814 | let mac = MacroDefId { |
795 | krate: self.expander.module.krate, | 815 | krate: self.expander.def_map.krate(), |
796 | ast_id: Some(self.expander.ast_id(&e)), | 816 | ast_id: Some(self.expander.ast_id(&e)), |
797 | kind: MacroDefKind::Declarative, | 817 | kind: MacroDefKind::Declarative, |
798 | local_inner: false, | 818 | local_inner: false, |
@@ -830,9 +850,9 @@ impl ExprCollector<'_> { | |||
830 | if annotation == BindingAnnotation::Unannotated && subpat.is_none() { | 850 | if annotation == BindingAnnotation::Unannotated && subpat.is_none() { |
831 | // This could also be a single-segment path pattern. To | 851 | // This could also be a single-segment path pattern. To |
832 | // decide that, we need to try resolving the name. | 852 | // decide that, we need to try resolving the name. |
833 | let (resolved, _) = self.expander.crate_def_map.resolve_path( | 853 | let (resolved, _) = self.expander.def_map.resolve_path( |
834 | self.db, | 854 | self.db, |
835 | self.expander.module.local_id, | 855 | self.expander.module, |
836 | &name.clone().into(), | 856 | &name.clone().into(), |
837 | BuiltinShadowMode::Other, | 857 | BuiltinShadowMode::Other, |
838 | ); | 858 | ); |
@@ -1045,11 +1065,16 @@ impl From<ast::LiteralKind> for Literal { | |||
1045 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { | 1065 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { |
1046 | match ast_lit_kind { | 1066 | match ast_lit_kind { |
1047 | LiteralKind::IntNumber(lit) => { | 1067 | LiteralKind::IntNumber(lit) => { |
1048 | if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { | 1068 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { |
1049 | return Literal::Float(Default::default(), Some(float_suffix)); | 1069 | return Literal::Float(Default::default(), builtin); |
1070 | } else if let builtin @ Some(_) = | ||
1071 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) | ||
1072 | { | ||
1073 | Literal::Int(Default::default(), builtin) | ||
1074 | } else { | ||
1075 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); | ||
1076 | Literal::Uint(Default::default(), builtin) | ||
1050 | } | 1077 | } |
1051 | let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)); | ||
1052 | Literal::Int(Default::default(), ty) | ||
1053 | } | 1078 | } |
1054 | LiteralKind::FloatNumber(lit) => { | 1079 | LiteralKind::FloatNumber(lit) => { |
1055 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1080 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); |
@@ -1057,7 +1082,7 @@ impl From<ast::LiteralKind> for Literal { | |||
1057 | } | 1082 | } |
1058 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), | 1083 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), |
1059 | LiteralKind::String(_) => Literal::String(Default::default()), | 1084 | LiteralKind::String(_) => Literal::String(Default::default()), |
1060 | LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), | 1085 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), |
1061 | LiteralKind::Bool(val) => Literal::Bool(val), | 1086 | LiteralKind::Bool(val) => Literal::Bool(val), |
1062 | LiteralKind::Char => Literal::Char(Default::default()), | 1087 | LiteralKind::Char => Literal::Char(Default::default()), |
1063 | } | 1088 | } |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 49f1427b4..210b4a617 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | body::Body, | 9 | body::Body, |
10 | db::DefDatabase, | 10 | db::DefDatabase, |
11 | expr::{Expr, ExprId, Pat, PatId, Statement}, | 11 | expr::{Expr, ExprId, Pat, PatId, Statement}, |
12 | DefWithBodyId, | 12 | BlockId, DefWithBodyId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub type ScopeId = Idx<ScopeData>; | 15 | pub type ScopeId = Idx<ScopeData>; |
@@ -39,6 +39,7 @@ impl ScopeEntry { | |||
39 | #[derive(Debug, PartialEq, Eq)] | 39 | #[derive(Debug, PartialEq, Eq)] |
40 | pub struct ScopeData { | 40 | pub struct ScopeData { |
41 | parent: Option<ScopeId>, | 41 | parent: Option<ScopeId>, |
42 | block: Option<BlockId>, | ||
42 | entries: Vec<ScopeEntry>, | 43 | entries: Vec<ScopeEntry>, |
43 | } | 44 | } |
44 | 45 | ||
@@ -61,6 +62,11 @@ impl ExprScopes { | |||
61 | &self.scopes[scope].entries | 62 | &self.scopes[scope].entries |
62 | } | 63 | } |
63 | 64 | ||
65 | /// If `scope` refers to a block expression scope, returns the corresponding `BlockId`. | ||
66 | pub fn block(&self, scope: ScopeId) -> Option<BlockId> { | ||
67 | self.scopes[scope].block | ||
68 | } | ||
69 | |||
64 | pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { | 70 | pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { |
65 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) | 71 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) |
66 | } | 72 | } |
@@ -79,11 +85,15 @@ impl ExprScopes { | |||
79 | } | 85 | } |
80 | 86 | ||
81 | fn root_scope(&mut self) -> ScopeId { | 87 | fn root_scope(&mut self) -> ScopeId { |
82 | self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) | 88 | self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] }) |
83 | } | 89 | } |
84 | 90 | ||
85 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { | 91 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { |
86 | self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) | 92 | self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] }) |
93 | } | ||
94 | |||
95 | fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId { | ||
96 | self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] }) | ||
87 | } | 97 | } |
88 | 98 | ||
89 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { | 99 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { |
@@ -136,7 +146,11 @@ fn compute_block_scopes( | |||
136 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { | 146 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { |
137 | scopes.set_scope(expr, scope); | 147 | scopes.set_scope(expr, scope); |
138 | match &body[expr] { | 148 | match &body[expr] { |
139 | Expr::Block { statements, tail, .. } => { | 149 | Expr::Block { statements, tail, id, .. } => { |
150 | let scope = scopes.new_block_scope(scope, *id); | ||
151 | // Overwrite the old scope for the block expr, so that every block scope can be found | ||
152 | // via the block itself (important for blocks that only contain items, no expressions). | ||
153 | scopes.set_scope(expr, scope); | ||
140 | compute_block_scopes(&statements, *tail, body, scopes, scope); | 154 | compute_block_scopes(&statements, *tail, body, scopes, scope); |
141 | } | 155 | } |
142 | Expr::For { iterable, pat, body: body_expr, .. } => { | 156 | Expr::For { iterable, pat, body: body_expr, .. } => { |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index de77d5fc9..bb43569d7 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | mod block; | ||
2 | |||
1 | use base_db::{fixture::WithFixture, SourceDatabase}; | 3 | use base_db::{fixture::WithFixture, SourceDatabase}; |
4 | use expect_test::Expect; | ||
2 | use test_utils::mark; | 5 | use test_utils::mark; |
3 | 6 | ||
4 | use crate::{test_db::TestDB, ModuleDefId}; | 7 | use crate::{test_db::TestDB, ModuleDefId}; |
@@ -6,18 +9,24 @@ use crate::{test_db::TestDB, ModuleDefId}; | |||
6 | use super::*; | 9 | use super::*; |
7 | 10 | ||
8 | fn lower(ra_fixture: &str) -> Arc<Body> { | 11 | fn lower(ra_fixture: &str) -> Arc<Body> { |
9 | let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); | 12 | let db = crate::test_db::TestDB::with_files(ra_fixture); |
10 | 13 | ||
11 | let krate = db.crate_graph().iter().next().unwrap(); | 14 | let krate = db.crate_graph().iter().next().unwrap(); |
12 | let def_map = db.crate_def_map(krate); | 15 | let def_map = db.crate_def_map(krate); |
13 | let module = def_map.modules_for_file(file_id).next().unwrap(); | 16 | let mut fn_def = None; |
14 | let module = &def_map[module]; | 17 | 'outer: for (_, module) in def_map.modules() { |
15 | let fn_def = match module.scope.declarations().next().unwrap() { | 18 | for decl in module.scope.declarations() { |
16 | ModuleDefId::FunctionId(it) => it, | 19 | match decl { |
17 | _ => panic!(), | 20 | ModuleDefId::FunctionId(it) => { |
18 | }; | 21 | fn_def = Some(it); |
22 | break 'outer; | ||
23 | } | ||
24 | _ => {} | ||
25 | } | ||
26 | } | ||
27 | } | ||
19 | 28 | ||
20 | db.body(fn_def.into()) | 29 | db.body(fn_def.unwrap().into()) |
21 | } | 30 | } |
22 | 31 | ||
23 | fn check_diagnostics(ra_fixture: &str) { | 32 | fn check_diagnostics(ra_fixture: &str) { |
@@ -25,6 +34,18 @@ fn check_diagnostics(ra_fixture: &str) { | |||
25 | db.check_diagnostics(); | 34 | db.check_diagnostics(); |
26 | } | 35 | } |
27 | 36 | ||
37 | fn block_def_map_at(ra_fixture: &str) -> String { | ||
38 | let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); | ||
39 | |||
40 | let module = db.module_at_position(position); | ||
41 | module.def_map(&db).dump(&db) | ||
42 | } | ||
43 | |||
44 | fn check_at(ra_fixture: &str, expect: Expect) { | ||
45 | let actual = block_def_map_at(ra_fixture); | ||
46 | expect.assert_eq(&actual); | ||
47 | } | ||
48 | |||
28 | #[test] | 49 | #[test] |
29 | fn your_stack_belongs_to_me() { | 50 | fn your_stack_belongs_to_me() { |
30 | mark::check!(your_stack_belongs_to_me); | 51 | mark::check!(your_stack_belongs_to_me); |
@@ -42,6 +63,25 @@ fn main() { n_nuple!(1,2,3); } | |||
42 | } | 63 | } |
43 | 64 | ||
44 | #[test] | 65 | #[test] |
66 | fn macro_resolve() { | ||
67 | // Regression test for a path resolution bug introduced with inner item handling. | ||
68 | lower( | ||
69 | r" | ||
70 | macro_rules! vec { | ||
71 | () => { () }; | ||
72 | ($elem:expr; $n:expr) => { () }; | ||
73 | ($($x:expr),+ $(,)?) => { () }; | ||
74 | } | ||
75 | mod m { | ||
76 | fn outer() { | ||
77 | let _ = vec![FileSet::default(); self.len()]; | ||
78 | } | ||
79 | } | ||
80 | ", | ||
81 | ); | ||
82 | } | ||
83 | |||
84 | #[test] | ||
45 | fn cfg_diagnostics() { | 85 | fn cfg_diagnostics() { |
46 | check_diagnostics( | 86 | check_diagnostics( |
47 | r" | 87 | r" |
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs new file mode 100644 index 000000000..8bca72a17 --- /dev/null +++ b/crates/hir_def/src/body/tests/block.rs | |||
@@ -0,0 +1,290 @@ | |||
1 | use super::*; | ||
2 | use expect_test::expect; | ||
3 | |||
4 | #[test] | ||
5 | fn inner_item_smoke() { | ||
6 | check_at( | ||
7 | r#" | ||
8 | struct inner {} | ||
9 | fn outer() { | ||
10 | $0 | ||
11 | fn inner() {} | ||
12 | } | ||
13 | "#, | ||
14 | expect![[r#" | ||
15 | block scope | ||
16 | inner: v | ||
17 | |||
18 | crate | ||
19 | inner: t | ||
20 | outer: v | ||
21 | "#]], | ||
22 | ); | ||
23 | } | ||
24 | |||
25 | #[test] | ||
26 | fn use_from_crate() { | ||
27 | check_at( | ||
28 | r#" | ||
29 | struct Struct {} | ||
30 | fn outer() { | ||
31 | fn Struct() {} | ||
32 | use Struct as PlainStruct; | ||
33 | use crate::Struct as CrateStruct; | ||
34 | use self::Struct as SelfStruct; | ||
35 | use super::Struct as SuperStruct; | ||
36 | $0 | ||
37 | } | ||
38 | "#, | ||
39 | expect![[r#" | ||
40 | block scope | ||
41 | CrateStruct: t | ||
42 | PlainStruct: t v | ||
43 | SelfStruct: t | ||
44 | Struct: v | ||
45 | SuperStruct: _ | ||
46 | |||
47 | crate | ||
48 | Struct: t | ||
49 | outer: v | ||
50 | "#]], | ||
51 | ); | ||
52 | } | ||
53 | |||
54 | #[test] | ||
55 | fn merge_namespaces() { | ||
56 | check_at( | ||
57 | r#" | ||
58 | struct name {} | ||
59 | fn outer() { | ||
60 | fn name() {} | ||
61 | |||
62 | use name as imported; // should import both `name`s | ||
63 | |||
64 | $0 | ||
65 | } | ||
66 | "#, | ||
67 | expect![[r#" | ||
68 | block scope | ||
69 | imported: t v | ||
70 | name: v | ||
71 | |||
72 | crate | ||
73 | name: t | ||
74 | outer: v | ||
75 | "#]], | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | #[test] | ||
80 | fn nested_blocks() { | ||
81 | check_at( | ||
82 | r#" | ||
83 | fn outer() { | ||
84 | struct inner1 {} | ||
85 | fn inner() { | ||
86 | use inner1; | ||
87 | use outer; | ||
88 | fn inner2() {} | ||
89 | $0 | ||
90 | } | ||
91 | } | ||
92 | "#, | ||
93 | expect![[r#" | ||
94 | block scope | ||
95 | inner1: t | ||
96 | inner2: v | ||
97 | outer: v | ||
98 | |||
99 | block scope | ||
100 | inner: v | ||
101 | inner1: t | ||
102 | |||
103 | crate | ||
104 | outer: v | ||
105 | "#]], | ||
106 | ); | ||
107 | } | ||
108 | |||
109 | #[test] | ||
110 | fn super_imports() { | ||
111 | check_at( | ||
112 | r#" | ||
113 | mod module { | ||
114 | fn f() { | ||
115 | use super::Struct; | ||
116 | $0 | ||
117 | } | ||
118 | } | ||
119 | |||
120 | struct Struct {} | ||
121 | "#, | ||
122 | expect![[r#" | ||
123 | block scope | ||
124 | Struct: t | ||
125 | |||
126 | crate | ||
127 | Struct: t | ||
128 | module: t | ||
129 | |||
130 | crate::module | ||
131 | f: v | ||
132 | "#]], | ||
133 | ); | ||
134 | } | ||
135 | |||
136 | #[test] | ||
137 | fn legacy_macro_items() { | ||
138 | // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded | ||
139 | // correctly. | ||
140 | check_at( | ||
141 | r#" | ||
142 | macro_rules! hit { | ||
143 | () => { | ||
144 | struct Hit {} | ||
145 | } | ||
146 | } | ||
147 | |||
148 | fn f() { | ||
149 | hit!(); | ||
150 | $0 | ||
151 | } | ||
152 | "#, | ||
153 | expect![[r#" | ||
154 | block scope | ||
155 | Hit: t | ||
156 | |||
157 | crate | ||
158 | f: v | ||
159 | "#]], | ||
160 | ); | ||
161 | } | ||
162 | |||
163 | #[test] | ||
164 | fn macro_resolve() { | ||
165 | check_at( | ||
166 | r#" | ||
167 | //- /lib.rs crate:lib deps:core | ||
168 | use core::mark; | ||
169 | |||
170 | fn f() { | ||
171 | fn nested() { | ||
172 | mark::hit!(Hit); | ||
173 | $0 | ||
174 | } | ||
175 | } | ||
176 | //- /core.rs crate:core | ||
177 | pub mod mark { | ||
178 | #[macro_export] | ||
179 | macro_rules! _hit { | ||
180 | ($name:ident) => { | ||
181 | struct $name {} | ||
182 | } | ||
183 | } | ||
184 | |||
185 | pub use crate::_hit as hit; | ||
186 | } | ||
187 | "#, | ||
188 | expect![[r#" | ||
189 | block scope | ||
190 | Hit: t | ||
191 | |||
192 | block scope | ||
193 | nested: v | ||
194 | |||
195 | crate | ||
196 | f: v | ||
197 | mark: t | ||
198 | "#]], | ||
199 | ); | ||
200 | } | ||
201 | |||
202 | #[test] | ||
203 | fn macro_resolve_legacy() { | ||
204 | check_at( | ||
205 | r#" | ||
206 | //- /lib.rs | ||
207 | mod module; | ||
208 | |||
209 | //- /module.rs | ||
210 | macro_rules! m { | ||
211 | () => { | ||
212 | struct Def {} | ||
213 | }; | ||
214 | } | ||
215 | |||
216 | fn f() { | ||
217 | { | ||
218 | m!(); | ||
219 | $0 | ||
220 | } | ||
221 | } | ||
222 | "#, | ||
223 | expect![[r#" | ||
224 | block scope | ||
225 | Def: t | ||
226 | |||
227 | crate | ||
228 | module: t | ||
229 | |||
230 | crate::module | ||
231 | f: v | ||
232 | "#]], | ||
233 | ) | ||
234 | } | ||
235 | |||
236 | #[test] | ||
237 | fn super_does_not_resolve_to_block_module() { | ||
238 | check_at( | ||
239 | r#" | ||
240 | fn main() { | ||
241 | struct Struct {} | ||
242 | mod module { | ||
243 | use super::Struct; | ||
244 | |||
245 | $0 | ||
246 | } | ||
247 | } | ||
248 | "#, | ||
249 | expect![[r#" | ||
250 | block scope | ||
251 | Struct: t | ||
252 | module: t | ||
253 | |||
254 | block scope::module | ||
255 | Struct: _ | ||
256 | |||
257 | crate | ||
258 | main: v | ||
259 | "#]], | ||
260 | ); | ||
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 | 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 dcb00a1d9..65d85c86a 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -74,7 +74,7 @@ impl ChildBySource for ImplId { | |||
74 | 74 | ||
75 | impl ChildBySource for ModuleId { | 75 | impl ChildBySource for ModuleId { |
76 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 76 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { |
77 | let crate_def_map = db.crate_def_map(self.krate); | 77 | let crate_def_map = self.def_map(db); |
78 | let module_data = &crate_def_map[self.local_id]; | 78 | let module_data = &crate_def_map[self.local_id]; |
79 | module_data.scope.child_by_source(db) | 79 | module_data.scope.child_by_source(db) |
80 | } | 80 | } |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index e7b7724f7..d3380e0f4 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -41,9 +41,9 @@ impl FunctionData { | |||
41 | 41 | ||
42 | Arc::new(FunctionData { | 42 | Arc::new(FunctionData { |
43 | name: func.name.clone(), | 43 | name: func.name.clone(), |
44 | params: func.params.to_vec(), | 44 | params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), |
45 | ret_type: func.ret_type.clone(), | 45 | ret_type: item_tree[func.ret_type].clone(), |
46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(), | 46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
47 | has_self_param: func.has_self_param, | 47 | has_self_param: func.has_self_param, |
48 | has_body: func.has_body, | 48 | has_body: func.has_body, |
49 | is_unsafe: func.is_unsafe, | 49 | is_unsafe: func.is_unsafe, |
@@ -75,7 +75,7 @@ impl TypeAliasData { | |||
75 | 75 | ||
76 | Arc::new(TypeAliasData { | 76 | Arc::new(TypeAliasData { |
77 | name: typ.name.clone(), | 77 | name: typ.name.clone(), |
78 | type_ref: typ.type_ref.clone(), | 78 | type_ref: typ.type_ref.map(|id| item_tree[id].clone()), |
79 | visibility: item_tree[typ.visibility].clone(), | 79 | visibility: item_tree[typ.visibility].clone(), |
80 | is_extern: typ.is_extern, | 80 | is_extern: typ.is_extern, |
81 | bounds: typ.bounds.to_vec(), | 81 | bounds: typ.bounds.to_vec(), |
@@ -144,8 +144,8 @@ impl ImplData { | |||
144 | 144 | ||
145 | let item_tree = db.item_tree(impl_loc.id.file_id); | 145 | let item_tree = db.item_tree(impl_loc.id.file_id); |
146 | let impl_def = &item_tree[impl_loc.id.value]; | 146 | let impl_def = &item_tree[impl_loc.id.value]; |
147 | let target_trait = impl_def.target_trait.clone(); | 147 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); |
148 | let target_type = 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.module(db); |
151 | let container = AssocContainerId::ImplId(id); | 151 | let container = AssocContainerId::ImplId(id); |
@@ -182,7 +182,7 @@ impl ConstData { | |||
182 | 182 | ||
183 | Arc::new(ConstData { | 183 | Arc::new(ConstData { |
184 | name: konst.name.clone(), | 184 | name: konst.name.clone(), |
185 | type_ref: konst.type_ref.clone(), | 185 | type_ref: item_tree[konst.type_ref].clone(), |
186 | visibility: item_tree[konst.visibility].clone(), | 186 | visibility: item_tree[konst.visibility].clone(), |
187 | }) | 187 | }) |
188 | } | 188 | } |
@@ -205,7 +205,7 @@ impl StaticData { | |||
205 | 205 | ||
206 | Arc::new(StaticData { | 206 | Arc::new(StaticData { |
207 | name: Some(statik.name.clone()), | 207 | name: Some(statik.name.clone()), |
208 | type_ref: statik.type_ref.clone(), | 208 | type_ref: item_tree[statik.type_ref].clone(), |
209 | visibility: item_tree[statik.visibility].clone(), | 209 | visibility: item_tree[statik.visibility].clone(), |
210 | mutable: statik.mutable, | 210 | mutable: statik.mutable, |
211 | is_extern: statik.is_extern, | 211 | is_extern: statik.is_extern, |
@@ -262,7 +262,7 @@ fn collect_items( | |||
262 | let root = db.parse_or_expand(file_id).unwrap(); | 262 | let root = db.parse_or_expand(file_id).unwrap(); |
263 | let call = ast_id_map.get(call.ast_id).to_node(&root); | 263 | let call = ast_id_map.get(call.ast_id).to_node(&root); |
264 | 264 | ||
265 | if let Some((mark, mac)) = expander.enter_expand(db, None, call).value { | 265 | if let Some((mark, mac)) = expander.enter_expand(db, call).value { |
266 | let src: InFile<ast::MacroItems> = expander.to_source(mac); | 266 | let src: InFile<ast::MacroItems> = expander.to_source(mac); |
267 | let item_tree = db.item_tree(src.file_id); | 267 | let item_tree = db.item_tree(src.file_id); |
268 | let iter = | 268 | let iter = |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 6ef9fe790..6c01f1ed0 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -15,10 +15,11 @@ use crate::{ | |||
15 | import_map::ImportMap, | 15 | import_map::ImportMap, |
16 | item_tree::ItemTree, | 16 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::CrateDefMap, | 18 | nameres::DefMap, |
19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, |
20 | GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, | 20 | FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, |
21 | StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, | 21 | StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, |
22 | UnionLoc, VariantId, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | #[salsa::query_group(InternDatabaseStorage)] | 25 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -41,6 +42,8 @@ pub trait InternDatabase: SourceDatabase { | |||
41 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; | 42 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; |
42 | #[salsa::interned] | 43 | #[salsa::interned] |
43 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; | 44 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; |
45 | #[salsa::interned] | ||
46 | fn intern_block(&self, loc: BlockLoc) -> BlockId; | ||
44 | } | 47 | } |
45 | 48 | ||
46 | #[salsa::query_group(DefDatabaseStorage)] | 49 | #[salsa::query_group(DefDatabaseStorage)] |
@@ -50,10 +53,28 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
50 | 53 | ||
51 | #[salsa::invoke(crate_def_map_wait)] | 54 | #[salsa::invoke(crate_def_map_wait)] |
52 | #[salsa::transparent] | 55 | #[salsa::transparent] |
53 | fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; | 56 | fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>; |
54 | 57 | ||
55 | #[salsa::invoke(CrateDefMap::crate_def_map_query)] | 58 | #[salsa::invoke(DefMap::crate_def_map_query)] |
56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<CrateDefMap>; | 59 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; |
60 | |||
61 | /// Computes the block-level `DefMap`, returning `None` when `block` doesn't contain any inner | ||
62 | /// items directly. | ||
63 | /// | ||
64 | /// For example: | ||
65 | /// | ||
66 | /// ``` | ||
67 | /// fn f() { // (0) | ||
68 | /// { // (1) | ||
69 | /// fn inner() {} | ||
70 | /// } | ||
71 | /// } | ||
72 | /// ``` | ||
73 | /// | ||
74 | /// The `block_def_map` for block 0 would return `None`, while `block_def_map` of block 1 would | ||
75 | /// return a `DefMap` containing `inner`. | ||
76 | #[salsa::invoke(DefMap::block_def_map_query)] | ||
77 | fn block_def_map(&self, block: BlockId) -> Option<Arc<DefMap>>; | ||
57 | 78 | ||
58 | #[salsa::invoke(StructData::struct_data_query)] | 79 | #[salsa::invoke(StructData::struct_data_query)] |
59 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | 80 | fn struct_data(&self, id: StructId) -> Arc<StructData>; |
@@ -112,7 +133,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
112 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; | 133 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; |
113 | } | 134 | } |
114 | 135 | ||
115 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 136 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<DefMap> { |
116 | let _p = profile::span("crate_def_map:wait"); | 137 | let _p = profile::span("crate_def_map:wait"); |
117 | db.crate_def_map_query(krate) | 138 | db.crate_def_map_query(krate) |
118 | } | 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 5be838f4a..24be93773 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -17,9 +17,10 @@ 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 | }; | 24 | }; |
24 | 25 | ||
25 | pub type ExprId = Idx<Expr>; | 26 | pub type ExprId = Idx<Expr>; |
@@ -42,6 +43,7 @@ pub enum Literal { | |||
42 | Char(char), | 43 | Char(char), |
43 | Bool(bool), | 44 | Bool(bool), |
44 | Int(u64, Option<BuiltinInt>), | 45 | Int(u64, Option<BuiltinInt>), |
46 | Uint(u64, Option<BuiltinUint>), | ||
45 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq | 47 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq |
46 | } | 48 | } |
47 | 49 | ||
@@ -56,6 +58,7 @@ pub enum Expr { | |||
56 | else_branch: Option<ExprId>, | 58 | else_branch: Option<ExprId>, |
57 | }, | 59 | }, |
58 | Block { | 60 | Block { |
61 | id: BlockId, | ||
59 | statements: Vec<Statement>, | 62 | statements: Vec<Statement>, |
60 | tail: Option<ExprId>, | 63 | tail: Option<ExprId>, |
61 | label: Option<LabelId>, | 64 | label: Option<LabelId>, |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 4a212d291..3e19a7702 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -1,10 +1,12 @@ | |||
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; | 7 | use test_utils::mark; |
6 | 8 | ||
7 | use crate::nameres::CrateDefMap; | 9 | use crate::nameres::DefMap; |
8 | use crate::{ | 10 | use crate::{ |
9 | db::DefDatabase, | 11 | db::DefDatabase, |
10 | item_scope::ItemInNs, | 12 | item_scope::ItemInNs, |
@@ -13,8 +15,6 @@ use crate::{ | |||
13 | ModuleDefId, ModuleId, | 15 | ModuleDefId, ModuleId, |
14 | }; | 16 | }; |
15 | 17 | ||
16 | // FIXME: handle local items | ||
17 | |||
18 | /// Find a path that can be used to refer to a certain item. This can depend on | 18 | /// Find a path that can be used to refer to a certain item. This can depend on |
19 | /// *from where* you're referring to the item, hence the `from` parameter. | 19 | /// *from where* you're referring to the item, hence the `from` parameter. |
20 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 20 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { |
@@ -36,29 +36,25 @@ const MAX_PATH_LEN: usize = 15; | |||
36 | 36 | ||
37 | impl ModPath { | 37 | impl ModPath { |
38 | fn starts_with_std(&self) -> bool { | 38 | fn starts_with_std(&self) -> bool { |
39 | self.segments.first() == Some(&known::std) | 39 | self.segments().first() == Some(&known::std) |
40 | } | 40 | } |
41 | 41 | ||
42 | // When std library is present, paths starting with `std::` | 42 | // When std library is present, paths starting with `std::` |
43 | // should be preferred over paths starting with `core::` and `alloc::` | 43 | // should be preferred over paths starting with `core::` and `alloc::` |
44 | fn can_start_with_std(&self) -> bool { | 44 | fn can_start_with_std(&self) -> bool { |
45 | let first_segment = self.segments.first(); | 45 | let first_segment = self.segments().first(); |
46 | first_segment == Some(&known::alloc) || first_segment == Some(&known::core) | 46 | first_segment == Some(&known::alloc) || first_segment == Some(&known::core) |
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | fn check_self_super(def_map: &CrateDefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 50 | fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> { |
51 | if item == ItemInNs::Types(from.into()) { | 51 | if item == ItemInNs::Types(from.into()) { |
52 | // - if the item is the module we're in, use `self` | 52 | // - if the item is the module we're in, use `self` |
53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) | 53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) |
54 | } else if let Some(parent_id) = def_map.modules[from.local_id].parent { | 54 | } else if let Some(parent_id) = def_map[from.local_id].parent { |
55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) | 55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) |
56 | if item | 56 | let parent_id = def_map.module_id(parent_id); |
57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 57 | if item == ItemInNs::Types(ModuleDefId::ModuleId(parent_id)) { |
58 | krate: from.krate, | ||
59 | local_id: parent_id, | ||
60 | })) | ||
61 | { | ||
62 | Some(ModPath::from_segments(PathKind::Super(1), Vec::new())) | 58 | Some(ModPath::from_segments(PathKind::Super(1), Vec::new())) |
63 | } else { | 59 | } else { |
64 | None | 60 | None |
@@ -101,7 +97,7 @@ fn find_path_inner( | |||
101 | item: ItemInNs, | 97 | item: ItemInNs, |
102 | from: ModuleId, | 98 | from: ModuleId, |
103 | max_len: usize, | 99 | max_len: usize, |
104 | prefixed: Option<PrefixKind>, | 100 | mut prefixed: Option<PrefixKind>, |
105 | ) -> Option<ModPath> { | 101 | ) -> Option<ModPath> { |
106 | if max_len == 0 { | 102 | if max_len == 0 { |
107 | return None; | 103 | return None; |
@@ -110,22 +106,19 @@ fn find_path_inner( | |||
110 | // Base cases: | 106 | // Base cases: |
111 | 107 | ||
112 | // - if the item is already in scope, return the name under which it is | 108 | // - if the item is already in scope, return the name under which it is |
113 | let def_map = db.crate_def_map(from.krate); | 109 | let def_map = from.def_map(db); |
114 | let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope; | 110 | let scope_name = def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { |
115 | let scope_name = | 111 | def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone()) |
116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; | 112 | }); |
117 | if prefixed.is_none() && scope_name.is_some() { | 113 | if prefixed.is_none() && scope_name.is_some() { |
118 | return scope_name | 114 | return scope_name |
119 | .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name])); | 115 | .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name])); |
120 | } | 116 | } |
121 | 117 | ||
122 | // - if the item is the crate root, return `crate` | 118 | // - if the item is the crate root, return `crate` |
123 | if item | 119 | let root = def_map.crate_root(db); |
124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 120 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { |
125 | krate: from.krate, | 121 | // FIXME: the `block_id()` check should be unnecessary, but affects the result |
126 | local_id: def_map.root, | ||
127 | })) | ||
128 | { | ||
129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 122 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
130 | } | 123 | } |
131 | 124 | ||
@@ -136,7 +129,7 @@ fn find_path_inner( | |||
136 | } | 129 | } |
137 | 130 | ||
138 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude | 131 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude |
139 | for (name, def_id) in &def_map.extern_prelude { | 132 | for (name, def_id) in def_map.extern_prelude() { |
140 | if item == ItemInNs::Types(*def_id) { | 133 | if item == ItemInNs::Types(*def_id) { |
141 | let name = scope_name.unwrap_or_else(|| name.clone()); | 134 | let name = scope_name.unwrap_or_else(|| name.clone()); |
142 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); | 135 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); |
@@ -144,10 +137,10 @@ fn find_path_inner( | |||
144 | } | 137 | } |
145 | 138 | ||
146 | // - if the item is in the prelude, return the name from there | 139 | // - if the item is in the prelude, return the name from there |
147 | if let Some(prelude_module) = def_map.prelude { | 140 | if let Some(prelude_module) = def_map.prelude() { |
148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); | 141 | let prelude_def_map = prelude_module.def_map(db); |
149 | let prelude_scope: &crate::item_scope::ItemScope = | 142 | let prelude_scope: &crate::item_scope::ItemScope = |
150 | &prelude_def_map.modules[prelude_module.local_id].scope; | 143 | &prelude_def_map[prelude_module.local_id].scope; |
151 | if let Some((name, vis)) = prelude_scope.name_of(item) { | 144 | if let Some((name, vis)) = prelude_scope.name_of(item) { |
152 | if vis.is_visible_from(db, from) { | 145 | if vis.is_visible_from(db, from) { |
153 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); | 146 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); |
@@ -165,7 +158,7 @@ fn find_path_inner( | |||
165 | if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { | 158 | if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { |
166 | if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) { | 159 | if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) { |
167 | let data = db.enum_data(variant.parent); | 160 | let data = db.enum_data(variant.parent); |
168 | path.segments.push(data.variants[variant.local_id].name.clone()); | 161 | path.push_segment(data.variants[variant.local_id].name.clone()); |
169 | return Some(path); | 162 | return Some(path); |
170 | } | 163 | } |
171 | // If this doesn't work, it seems we have no way of referring to the | 164 | // If this doesn't work, it seems we have no way of referring to the |
@@ -175,7 +168,7 @@ fn find_path_inner( | |||
175 | 168 | ||
176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 169 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
177 | 170 | ||
178 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | 171 | let crate_root = def_map.crate_root(db); |
179 | let crate_attrs = db.attrs(crate_root.into()); | 172 | let crate_attrs = db.attrs(crate_root.into()); |
180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 173 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
181 | let mut best_path = None; | 174 | let mut best_path = None; |
@@ -194,7 +187,7 @@ fn find_path_inner( | |||
194 | best_path_len - 1, | 187 | best_path_len - 1, |
195 | prefixed, | 188 | prefixed, |
196 | ) { | 189 | ) { |
197 | path.segments.push(name); | 190 | path.push_segment(name); |
198 | 191 | ||
199 | let new_path = if let Some(best_path) = best_path { | 192 | let new_path = if let Some(best_path) = best_path { |
200 | select_best_path(best_path, path, prefer_no_std) | 193 | select_best_path(best_path, path, prefer_no_std) |
@@ -223,7 +216,7 @@ fn find_path_inner( | |||
223 | prefixed, | 216 | prefixed, |
224 | )?; | 217 | )?; |
225 | mark::hit!(partially_imported); | 218 | mark::hit!(partially_imported); |
226 | path.segments.push(info.path.segments.last().unwrap().clone()); | 219 | path.push_segment(info.path.segments.last().unwrap().clone()); |
227 | Some(path) | 220 | Some(path) |
228 | }) | 221 | }) |
229 | }); | 222 | }); |
@@ -238,6 +231,15 @@ fn find_path_inner( | |||
238 | } | 231 | } |
239 | } | 232 | } |
240 | 233 | ||
234 | // If the item is declared inside a block expression, don't use a prefix, as we don't handle | ||
235 | // that correctly (FIXME). | ||
236 | if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) { | ||
237 | if item_module.def_map(db).block_id().is_some() && prefixed.is_some() { | ||
238 | mark::hit!(prefixed_in_block_expression); | ||
239 | prefixed = Some(PrefixKind::Plain); | ||
240 | } | ||
241 | } | ||
242 | |||
241 | if let Some(prefix) = prefixed.map(PrefixKind::prefix) { | 243 | if let Some(prefix) = prefixed.map(PrefixKind::prefix) { |
242 | best_path.or_else(|| { | 244 | best_path.or_else(|| { |
243 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) | 245 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) |
@@ -283,22 +285,19 @@ fn find_local_import_locations( | |||
283 | // above `from` with any visibility. That means we do not need to descend into private siblings | 285 | // above `from` with any visibility. That means we do not need to descend into private siblings |
284 | // of `from` (and similar). | 286 | // of `from` (and similar). |
285 | 287 | ||
286 | let def_map = db.crate_def_map(from.krate); | 288 | let def_map = from.def_map(db); |
287 | 289 | ||
288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all | 290 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all |
289 | // of its (recursive) parent modules. | 291 | // of its (recursive) parent modules. |
290 | let data = &def_map.modules[from.local_id]; | 292 | let data = &def_map[from.local_id]; |
291 | let mut worklist = data | 293 | let mut worklist = |
292 | .children | 294 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
293 | .values() | 295 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { |
294 | .map(|child| ModuleId { krate: from.krate, local_id: *child }) | 296 | worklist.push(ancestor); |
295 | .collect::<Vec<_>>(); | ||
296 | let mut parent = data.parent; | ||
297 | while let Some(p) = parent { | ||
298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); | ||
299 | parent = def_map.modules[p].parent; | ||
300 | } | 297 | } |
301 | 298 | ||
299 | let def_map = def_map.crate_root(db).def_map(db); | ||
300 | |||
302 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 301 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
303 | 302 | ||
304 | let mut locations = Vec::new(); | 303 | let mut locations = Vec::new(); |
@@ -309,10 +308,17 @@ fn find_local_import_locations( | |||
309 | 308 | ||
310 | let ext_def_map; | 309 | let ext_def_map; |
311 | let data = if module.krate == from.krate { | 310 | let data = if module.krate == from.krate { |
312 | &def_map[module.local_id] | 311 | if module.block.is_some() { |
312 | // Re-query the block's DefMap | ||
313 | ext_def_map = module.def_map(db); | ||
314 | &ext_def_map[module.local_id] | ||
315 | } else { | ||
316 | // Reuse the root DefMap | ||
317 | &def_map[module.local_id] | ||
318 | } | ||
313 | } else { | 319 | } else { |
314 | // The crate might reexport a module defined in another crate. | 320 | // The crate might reexport a module defined in another crate. |
315 | ext_def_map = db.crate_def_map(module.krate); | 321 | ext_def_map = module.def_map(db); |
316 | &ext_def_map[module.local_id] | 322 | &ext_def_map[module.local_id] |
317 | }; | 323 | }; |
318 | 324 | ||
@@ -369,14 +375,14 @@ mod tests { | |||
369 | /// module the cursor is in. | 375 | /// module the cursor is in. |
370 | fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) { | 376 | fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) { |
371 | let (db, pos) = TestDB::with_position(ra_fixture); | 377 | let (db, pos) = TestDB::with_position(ra_fixture); |
372 | let module = db.module_for_file(pos.file_id); | 378 | let module = db.module_at_position(pos); |
373 | let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path)); | 379 | let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path)); |
374 | let ast_path = | 380 | let ast_path = |
375 | parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); | 381 | parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); |
376 | let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); | 382 | let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); |
377 | 383 | ||
378 | let crate_def_map = db.crate_def_map(module.krate); | 384 | let def_map = module.def_map(&db); |
379 | let resolved = crate_def_map | 385 | let resolved = def_map |
380 | .resolve_path( | 386 | .resolve_path( |
381 | &db, | 387 | &db, |
382 | module.local_id, | 388 | module.local_id, |
@@ -799,4 +805,103 @@ mod tests { | |||
799 | check_found_path(code, "u8", "u8", "u8", "u8"); | 805 | check_found_path(code, "u8", "u8", "u8", "u8"); |
800 | check_found_path(code, "u16", "u16", "u16", "u16"); | 806 | check_found_path(code, "u16", "u16", "u16", "u16"); |
801 | } | 807 | } |
808 | |||
809 | #[test] | ||
810 | fn inner_items() { | ||
811 | check_found_path( | ||
812 | r#" | ||
813 | fn main() { | ||
814 | struct Inner {} | ||
815 | $0 | ||
816 | } | ||
817 | "#, | ||
818 | "Inner", | ||
819 | "Inner", | ||
820 | "Inner", | ||
821 | "Inner", | ||
822 | ); | ||
823 | } | ||
824 | |||
825 | #[test] | ||
826 | fn inner_items_from_outer_scope() { | ||
827 | check_found_path( | ||
828 | r#" | ||
829 | fn main() { | ||
830 | struct Struct {} | ||
831 | { | ||
832 | $0 | ||
833 | } | ||
834 | } | ||
835 | "#, | ||
836 | "Struct", | ||
837 | "Struct", | ||
838 | "Struct", | ||
839 | "Struct", | ||
840 | ); | ||
841 | } | ||
842 | |||
843 | #[test] | ||
844 | fn inner_items_from_inner_module() { | ||
845 | mark::check!(prefixed_in_block_expression); | ||
846 | check_found_path( | ||
847 | r#" | ||
848 | fn main() { | ||
849 | mod module { | ||
850 | struct Struct {} | ||
851 | } | ||
852 | { | ||
853 | $0 | ||
854 | } | ||
855 | } | ||
856 | "#, | ||
857 | "module::Struct", | ||
858 | "module::Struct", | ||
859 | "module::Struct", | ||
860 | "module::Struct", | ||
861 | ); | ||
862 | } | ||
863 | |||
864 | #[test] | ||
865 | #[ignore] | ||
866 | fn inner_items_from_parent_module() { | ||
867 | // FIXME: ItemTree currently associates all inner items with `main`. Luckily, this sort of | ||
868 | // code is very rare, so this isn't terrible. | ||
869 | // To fix it, we should probably build dedicated `ItemTree`s for inner items, and not store | ||
870 | // them in the file's main ItemTree. This would also allow us to stop parsing function | ||
871 | // bodies when we only want to compute the crate's main DefMap. | ||
872 | check_found_path( | ||
873 | r#" | ||
874 | fn main() { | ||
875 | struct Struct {} | ||
876 | mod module { | ||
877 | $0 | ||
878 | } | ||
879 | } | ||
880 | "#, | ||
881 | "super::Struct", | ||
882 | "super::Struct", | ||
883 | "super::Struct", | ||
884 | "super::Struct", | ||
885 | ); | ||
886 | } | ||
887 | |||
888 | #[test] | ||
889 | fn outer_items_with_inner_items_present() { | ||
890 | check_found_path( | ||
891 | r#" | ||
892 | mod module { | ||
893 | pub struct CompleteMe; | ||
894 | } | ||
895 | |||
896 | fn main() { | ||
897 | fn inner() {} | ||
898 | $0 | ||
899 | } | ||
900 | "#, | ||
901 | "module::CompleteMe", | ||
902 | "module::CompleteMe", | ||
903 | "crate::module::CompleteMe", | ||
904 | "self::module::CompleteMe", | ||
905 | ) | ||
906 | } | ||
802 | } | 907 | } |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index e5368b293..0a3dc7956 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -75,7 +75,7 @@ impl ImportMap { | |||
75 | 75 | ||
76 | // We look only into modules that are public(ly reexported), starting with the crate root. | 76 | // We look only into modules that are public(ly reexported), starting with the crate root. |
77 | let empty = ImportPath { segments: vec![] }; | 77 | let empty = ImportPath { segments: vec![] }; |
78 | let root = ModuleId { krate, local_id: def_map.root }; | 78 | let root = def_map.module_id(def_map.root()); |
79 | let mut worklist = vec![(root, empty)]; | 79 | let mut worklist = vec![(root, empty)]; |
80 | while let Some((module, mod_path)) = worklist.pop() { | 80 | while let Some((module, mod_path)) = worklist.pop() { |
81 | let ext_def_map; | 81 | let ext_def_map; |
@@ -83,7 +83,7 @@ impl ImportMap { | |||
83 | &def_map[module.local_id] | 83 | &def_map[module.local_id] |
84 | } else { | 84 | } else { |
85 | // The crate might reexport a module defined in another crate. | 85 | // The crate might reexport a module defined in another crate. |
86 | ext_def_map = db.crate_def_map(module.krate); | 86 | ext_def_map = module.def_map(db); |
87 | &ext_def_map[module.local_id] | 87 | &ext_def_map[module.local_id] |
88 | }; | 88 | }; |
89 | 89 | ||
@@ -263,6 +263,7 @@ pub enum ImportKind { | |||
263 | Trait, | 263 | Trait, |
264 | TypeAlias, | 264 | TypeAlias, |
265 | BuiltinType, | 265 | BuiltinType, |
266 | AssociatedItem, | ||
266 | } | 267 | } |
267 | 268 | ||
268 | /// A way to match import map contents against the search query. | 269 | /// A way to match import map contents against the search query. |
@@ -282,6 +283,7 @@ pub struct Query { | |||
282 | query: String, | 283 | query: String, |
283 | lowercased: String, | 284 | lowercased: String, |
284 | name_only: bool, | 285 | name_only: bool, |
286 | assoc_items_only: bool, | ||
285 | search_mode: SearchMode, | 287 | search_mode: SearchMode, |
286 | case_sensitive: bool, | 288 | case_sensitive: bool, |
287 | limit: usize, | 289 | limit: usize, |
@@ -295,6 +297,7 @@ impl Query { | |||
295 | query, | 297 | query, |
296 | lowercased, | 298 | lowercased, |
297 | name_only: false, | 299 | name_only: false, |
300 | assoc_items_only: false, | ||
298 | search_mode: SearchMode::Contains, | 301 | search_mode: SearchMode::Contains, |
299 | case_sensitive: false, | 302 | case_sensitive: false, |
300 | limit: usize::max_value(), | 303 | limit: usize::max_value(), |
@@ -309,6 +312,11 @@ impl Query { | |||
309 | Self { name_only: true, ..self } | 312 | Self { name_only: true, ..self } |
310 | } | 313 | } |
311 | 314 | ||
315 | /// Matches only the entries that are associated items, ignoring the rest. | ||
316 | pub fn assoc_items_only(self) -> Self { | ||
317 | Self { assoc_items_only: true, ..self } | ||
318 | } | ||
319 | |||
312 | /// Specifies the way to search for the entries using the query. | 320 | /// Specifies the way to search for the entries using the query. |
313 | pub fn search_mode(self, search_mode: SearchMode) -> Self { | 321 | pub fn search_mode(self, search_mode: SearchMode) -> Self { |
314 | Self { search_mode, ..self } | 322 | Self { search_mode, ..self } |
@@ -331,6 +339,14 @@ impl Query { | |||
331 | } | 339 | } |
332 | 340 | ||
333 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { | 341 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { |
342 | if import.is_trait_assoc_item { | ||
343 | if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { | ||
344 | return false; | ||
345 | } | ||
346 | } else if self.assoc_items_only { | ||
347 | return false; | ||
348 | } | ||
349 | |||
334 | let mut input = if import.is_trait_assoc_item || self.name_only { | 350 | let mut input = if import.is_trait_assoc_item || self.name_only { |
335 | import.path.segments.last().unwrap().to_string() | 351 | import.path.segments.last().unwrap().to_string() |
336 | } else { | 352 | } else { |
@@ -814,6 +830,56 @@ mod tests { | |||
814 | } | 830 | } |
815 | 831 | ||
816 | #[test] | 832 | #[test] |
833 | fn assoc_items_filtering() { | ||
834 | let ra_fixture = r#" | ||
835 | //- /main.rs crate:main deps:dep | ||
836 | //- /dep.rs crate:dep | ||
837 | pub mod fmt { | ||
838 | pub trait Display { | ||
839 | type FmtTypeAlias; | ||
840 | const FMT_CONST: bool; | ||
841 | |||
842 | fn format_function(); | ||
843 | fn format_method(&self); | ||
844 | } | ||
845 | } | ||
846 | "#; | ||
847 | |||
848 | check_search( | ||
849 | ra_fixture, | ||
850 | "main", | ||
851 | Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy).assoc_items_only(), | ||
852 | expect![[r#" | ||
853 | dep::fmt::Display::FMT_CONST (a) | ||
854 | dep::fmt::Display::format_function (a) | ||
855 | dep::fmt::Display::format_method (a) | ||
856 | "#]], | ||
857 | ); | ||
858 | |||
859 | check_search( | ||
860 | ra_fixture, | ||
861 | "main", | ||
862 | Query::new("fmt".to_string()) | ||
863 | .search_mode(SearchMode::Fuzzy) | ||
864 | .exclude_import_kind(ImportKind::AssociatedItem), | ||
865 | expect![[r#" | ||
866 | dep::fmt (t) | ||
867 | dep::fmt::Display (t) | ||
868 | "#]], | ||
869 | ); | ||
870 | |||
871 | check_search( | ||
872 | ra_fixture, | ||
873 | "main", | ||
874 | Query::new("fmt".to_string()) | ||
875 | .search_mode(SearchMode::Fuzzy) | ||
876 | .assoc_items_only() | ||
877 | .exclude_import_kind(ImportKind::AssociatedItem), | ||
878 | expect![[r#""#]], | ||
879 | ); | ||
880 | } | ||
881 | |||
882 | #[test] | ||
817 | fn search_mode() { | 883 | fn search_mode() { |
818 | let ra_fixture = r#" | 884 | let ra_fixture = r#" |
819 | //- /main.rs crate:main deps:dep | 885 | //- /main.rs crate:main deps:dep |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 2750e1c91..4e5daa2ff 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -8,11 +8,12 @@ use hir_expand::name::Name; | |||
8 | use hir_expand::MacroDefKind; | 8 | 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 test_utils::mark; | 12 | use test_utils::mark; |
12 | 13 | ||
13 | use crate::{ | 14 | use crate::{ |
14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, |
15 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, | 16 | LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, |
16 | }; | 17 | }; |
17 | 18 | ||
18 | #[derive(Copy, Clone)] | 19 | #[derive(Copy, Clone)] |
@@ -292,6 +293,30 @@ impl ItemScope { | |||
292 | *vis = Visibility::Module(this_module); | 293 | *vis = Visibility::Module(this_module); |
293 | } | 294 | } |
294 | } | 295 | } |
296 | |||
297 | pub(crate) fn dump(&self, buf: &mut String) { | ||
298 | let mut entries: Vec<_> = self.resolutions().collect(); | ||
299 | entries.sort_by_key(|(name, _)| name.clone()); | ||
300 | |||
301 | for (name, def) in entries { | ||
302 | format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string())); | ||
303 | |||
304 | if def.types.is_some() { | ||
305 | buf.push_str(" t"); | ||
306 | } | ||
307 | if def.values.is_some() { | ||
308 | buf.push_str(" v"); | ||
309 | } | ||
310 | if def.macros.is_some() { | ||
311 | buf.push_str(" m"); | ||
312 | } | ||
313 | if def.is_none() { | ||
314 | buf.push_str(" _"); | ||
315 | } | ||
316 | |||
317 | buf.push('\n'); | ||
318 | } | ||
319 | } | ||
295 | } | 320 | } |
296 | 321 | ||
297 | impl PerNs { | 322 | impl PerNs { |
@@ -350,19 +375,9 @@ impl ItemInNs { | |||
350 | 375 | ||
351 | /// Returns the crate defining this item (or `None` if `self` is built-in). | 376 | /// Returns the crate defining this item (or `None` if `self` is built-in). |
352 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | 377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { |
353 | Some(match self { | 378 | match self { |
354 | ItemInNs::Types(did) | ItemInNs::Values(did) => match did { | 379 | ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate), |
355 | ModuleDefId::ModuleId(id) => id.krate, | 380 | ItemInNs::Macros(id) => Some(id.krate), |
356 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, | 381 | } |
357 | ModuleDefId::AdtId(id) => id.module(db).krate, | ||
358 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate, | ||
359 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate, | ||
360 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate, | ||
361 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate, | ||
362 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | ||
363 | ModuleDefId::BuiltinType(_) => return None, | ||
364 | }, | ||
365 | ItemInNs::Macros(id) => return Some(id.krate), | ||
366 | }) | ||
367 | } | 382 | } |
368 | } | 383 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ff62928df..3233b1957 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -21,9 +21,10 @@ use hir_expand::{ | |||
21 | HirFileId, InFile, | 21 | HirFileId, InFile, |
22 | }; | 22 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | ||
24 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
25 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
26 | use syntax::{ast, match_ast}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
27 | use test_utils::mark; | 28 | use test_utils::mark; |
28 | 29 | ||
29 | use crate::{ | 30 | use crate::{ |
@@ -65,22 +66,27 @@ impl GenericParamsId { | |||
65 | } | 66 | } |
66 | 67 | ||
67 | /// The item tree of a source file. | 68 | /// The item tree of a source file. |
68 | #[derive(Debug, Eq, PartialEq)] | 69 | #[derive(Debug, Default, Eq, PartialEq)] |
69 | pub struct ItemTree { | 70 | pub struct ItemTree { |
71 | _c: Count<Self>, | ||
72 | |||
70 | top_level: SmallVec<[ModItem; 1]>, | 73 | top_level: SmallVec<[ModItem; 1]>, |
71 | attrs: FxHashMap<AttrOwner, RawAttrs>, | 74 | attrs: FxHashMap<AttrOwner, RawAttrs>, |
72 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, | ||
73 | 75 | ||
74 | data: Option<Box<ItemTreeData>>, | 76 | data: Option<Box<ItemTreeData>>, |
75 | } | 77 | } |
76 | 78 | ||
77 | impl ItemTree { | 79 | impl ItemTree { |
78 | pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { | 80 | pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { |
79 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); | 81 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); |
80 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { | 82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { |
83 | if node.kind() == SyntaxKind::ERROR { | ||
84 | // FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic | ||
85 | return Default::default(); | ||
86 | } | ||
81 | node | 87 | node |
82 | } else { | 88 | } else { |
83 | return Arc::new(Self::empty()); | 89 | return Default::default(); |
84 | }; | 90 | }; |
85 | 91 | ||
86 | let hygiene = Hygiene::new(db.upcast(), file_id); | 92 | let hygiene = Hygiene::new(db.upcast(), file_id); |
@@ -96,15 +102,17 @@ impl ItemTree { | |||
96 | ctx.lower_module_items(&items) | 102 | ctx.lower_module_items(&items) |
97 | }, | 103 | }, |
98 | ast::MacroStmts(stmts) => { | 104 | ast::MacroStmts(stmts) => { |
99 | ctx.lower_inner_items(stmts.syntax()) | 105 | // The produced statements can include items, which should be added as top-level |
106 | // items. | ||
107 | ctx.lower_macro_stmts(stmts) | ||
100 | }, | 108 | }, |
101 | // Macros can expand to expressions. We return an empty item tree in this case, but | ||
102 | // still need to collect inner items. | ||
103 | ast::Expr(e) => { | 109 | ast::Expr(e) => { |
110 | // Macros can expand to expressions. We return an empty item tree in this case, but | ||
111 | // still need to collect inner items. | ||
104 | ctx.lower_inner_items(e.syntax()) | 112 | ctx.lower_inner_items(e.syntax()) |
105 | }, | 113 | }, |
106 | _ => { | 114 | _ => { |
107 | panic!("cannot create item tree from {:?}", syntax); | 115 | panic!("cannot create item tree from {:?} {}", syntax, syntax); |
108 | }, | 116 | }, |
109 | } | 117 | } |
110 | }; | 118 | }; |
@@ -116,15 +124,6 @@ impl ItemTree { | |||
116 | Arc::new(item_tree) | 124 | Arc::new(item_tree) |
117 | } | 125 | } |
118 | 126 | ||
119 | fn empty() -> Self { | ||
120 | Self { | ||
121 | top_level: Default::default(), | ||
122 | attrs: Default::default(), | ||
123 | inner_items: Default::default(), | ||
124 | data: Default::default(), | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn shrink_to_fit(&mut self) { | 127 | fn shrink_to_fit(&mut self) { |
129 | if let Some(data) = &mut self.data { | 128 | if let Some(data) = &mut self.data { |
130 | let ItemTreeData { | 129 | let ItemTreeData { |
@@ -147,6 +146,8 @@ impl ItemTree { | |||
147 | macro_defs, | 146 | macro_defs, |
148 | vis, | 147 | vis, |
149 | generics, | 148 | generics, |
149 | type_refs, | ||
150 | inner_items, | ||
150 | } = &mut **data; | 151 | } = &mut **data; |
151 | 152 | ||
152 | imports.shrink_to_fit(); | 153 | imports.shrink_to_fit(); |
@@ -169,6 +170,10 @@ impl ItemTree { | |||
169 | 170 | ||
170 | vis.arena.shrink_to_fit(); | 171 | vis.arena.shrink_to_fit(); |
171 | generics.arena.shrink_to_fit(); | 172 | generics.arena.shrink_to_fit(); |
173 | type_refs.arena.shrink_to_fit(); | ||
174 | type_refs.map.shrink_to_fit(); | ||
175 | |||
176 | inner_items.shrink_to_fit(); | ||
172 | } | 177 | } |
173 | } | 178 | } |
174 | 179 | ||
@@ -191,16 +196,18 @@ impl ItemTree { | |||
191 | self.raw_attrs(of).clone().filter(db, krate) | 196 | self.raw_attrs(of).clone().filter(db, krate) |
192 | } | 197 | } |
193 | 198 | ||
194 | /// Returns the lowered inner items that `ast` corresponds to. | 199 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { |
195 | /// | 200 | match &self.data { |
196 | /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered | 201 | Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(), |
197 | /// to multiple items in the `ItemTree`. | 202 | None => None.into_iter().flatten(), |
198 | pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { | 203 | } |
199 | &self.inner_items[&ast] | ||
200 | } | 204 | } |
201 | 205 | ||
202 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { | 206 | pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] { |
203 | self.inner_items.values().flatten().copied() | 207 | match &self.data { |
208 | Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]), | ||
209 | None => &[], | ||
210 | } | ||
204 | } | 211 | } |
205 | 212 | ||
206 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | 213 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { |
@@ -233,7 +240,7 @@ impl ItemVisibilities { | |||
233 | fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { | 240 | fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { |
234 | match &vis { | 241 | match &vis { |
235 | RawVisibility::Public => RawVisibilityId::PUB, | 242 | RawVisibility::Public => RawVisibilityId::PUB, |
236 | RawVisibility::Module(path) if path.segments.is_empty() => match &path.kind { | 243 | RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind { |
237 | PathKind::Super(0) => RawVisibilityId::PRIV, | 244 | PathKind::Super(0) => RawVisibilityId::PRIV, |
238 | PathKind::Crate => RawVisibilityId::PUB_CRATE, | 245 | PathKind::Crate => RawVisibilityId::PUB_CRATE, |
239 | _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), | 246 | _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), |
@@ -244,10 +251,8 @@ impl ItemVisibilities { | |||
244 | } | 251 | } |
245 | 252 | ||
246 | static VIS_PUB: RawVisibility = RawVisibility::Public; | 253 | static VIS_PUB: RawVisibility = RawVisibility::Public; |
247 | static VIS_PRIV: RawVisibility = | 254 | static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))); |
248 | RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() }); | 255 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); |
249 | static VIS_PUB_CRATE: RawVisibility = | ||
250 | RawVisibility::Module(ModPath { kind: PathKind::Crate, segments: Vec::new() }); | ||
251 | 256 | ||
252 | #[derive(Default, Debug, Eq, PartialEq)] | 257 | #[derive(Default, Debug, Eq, PartialEq)] |
253 | struct GenericParamsStorage { | 258 | struct GenericParamsStorage { |
@@ -275,6 +280,32 @@ static EMPTY_GENERICS: GenericParams = GenericParams { | |||
275 | where_predicates: Vec::new(), | 280 | where_predicates: Vec::new(), |
276 | }; | 281 | }; |
277 | 282 | ||
283 | /// `TypeRef` interner. | ||
284 | #[derive(Default, Debug, Eq, PartialEq)] | ||
285 | struct TypeRefStorage { | ||
286 | arena: Arena<Arc<TypeRef>>, | ||
287 | map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>, | ||
288 | } | ||
289 | |||
290 | impl TypeRefStorage { | ||
291 | // Note: We lie about the `Idx<TypeRef>` to hide the interner details. | ||
292 | |||
293 | fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> { | ||
294 | if let Some(id) = self.map.get(&ty) { | ||
295 | return Idx::from_raw(id.into_raw()); | ||
296 | } | ||
297 | |||
298 | let ty = Arc::new(ty); | ||
299 | let idx = self.arena.alloc(ty.clone()); | ||
300 | self.map.insert(ty, idx); | ||
301 | Idx::from_raw(idx.into_raw()) | ||
302 | } | ||
303 | |||
304 | fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef { | ||
305 | &self.arena[Idx::from_raw(id.into_raw())] | ||
306 | } | ||
307 | } | ||
308 | |||
278 | #[derive(Default, Debug, Eq, PartialEq)] | 309 | #[derive(Default, Debug, Eq, PartialEq)] |
279 | struct ItemTreeData { | 310 | struct ItemTreeData { |
280 | imports: Arena<Import>, | 311 | imports: Arena<Import>, |
@@ -297,6 +328,9 @@ struct ItemTreeData { | |||
297 | 328 | ||
298 | vis: ItemVisibilities, | 329 | vis: ItemVisibilities, |
299 | generics: GenericParamsStorage, | 330 | generics: GenericParamsStorage, |
331 | type_refs: TypeRefStorage, | ||
332 | |||
333 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | ||
300 | } | 334 | } |
301 | 335 | ||
302 | #[derive(Debug, Eq, PartialEq, Hash)] | 336 | #[derive(Debug, Eq, PartialEq, Hash)] |
@@ -483,6 +517,14 @@ impl Index<GenericParamsId> for ItemTree { | |||
483 | } | 517 | } |
484 | } | 518 | } |
485 | 519 | ||
520 | impl Index<Idx<TypeRef>> for ItemTree { | ||
521 | type Output = TypeRef; | ||
522 | |||
523 | fn index(&self, id: Idx<TypeRef>) -> &Self::Output { | ||
524 | self.data().type_refs.lookup(id) | ||
525 | } | ||
526 | } | ||
527 | |||
486 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 528 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
487 | type Output = N; | 529 | type Output = N; |
488 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 530 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -526,9 +568,9 @@ pub struct Function { | |||
526 | /// Whether the function is located in an `extern` block (*not* whether it is an | 568 | /// Whether the function is located in an `extern` block (*not* whether it is an |
527 | /// `extern "abi" fn`). | 569 | /// `extern "abi" fn`). |
528 | pub is_extern: bool, | 570 | pub is_extern: bool, |
529 | pub params: Box<[TypeRef]>, | 571 | pub params: Box<[Idx<TypeRef>]>, |
530 | pub is_varargs: bool, | 572 | pub is_varargs: bool, |
531 | pub ret_type: TypeRef, | 573 | pub ret_type: Idx<TypeRef>, |
532 | pub ast_id: FileAstId<ast::Fn>, | 574 | pub ast_id: FileAstId<ast::Fn>, |
533 | } | 575 | } |
534 | 576 | ||
@@ -575,7 +617,7 @@ pub struct Const { | |||
575 | /// const _: () = (); | 617 | /// const _: () = (); |
576 | pub name: Option<Name>, | 618 | pub name: Option<Name>, |
577 | pub visibility: RawVisibilityId, | 619 | pub visibility: RawVisibilityId, |
578 | pub type_ref: TypeRef, | 620 | pub type_ref: Idx<TypeRef>, |
579 | pub ast_id: FileAstId<ast::Const>, | 621 | pub ast_id: FileAstId<ast::Const>, |
580 | } | 622 | } |
581 | 623 | ||
@@ -586,7 +628,7 @@ pub struct Static { | |||
586 | pub mutable: bool, | 628 | pub mutable: bool, |
587 | /// Whether the static is in an `extern` block. | 629 | /// Whether the static is in an `extern` block. |
588 | pub is_extern: bool, | 630 | pub is_extern: bool, |
589 | pub type_ref: TypeRef, | 631 | pub type_ref: Idx<TypeRef>, |
590 | pub ast_id: FileAstId<ast::Static>, | 632 | pub ast_id: FileAstId<ast::Static>, |
591 | } | 633 | } |
592 | 634 | ||
@@ -603,8 +645,8 @@ pub struct Trait { | |||
603 | #[derive(Debug, Clone, Eq, PartialEq)] | 645 | #[derive(Debug, Clone, Eq, PartialEq)] |
604 | pub struct Impl { | 646 | pub struct Impl { |
605 | pub generic_params: GenericParamsId, | 647 | pub generic_params: GenericParamsId, |
606 | pub target_trait: Option<TypeRef>, | 648 | pub target_trait: Option<Idx<TypeRef>>, |
607 | pub target_type: TypeRef, | 649 | pub target_type: Idx<TypeRef>, |
608 | pub is_negative: bool, | 650 | pub is_negative: bool, |
609 | pub items: Box<[AssocItem]>, | 651 | pub items: Box<[AssocItem]>, |
610 | pub ast_id: FileAstId<ast::Impl>, | 652 | pub ast_id: FileAstId<ast::Impl>, |
@@ -617,7 +659,7 @@ pub struct TypeAlias { | |||
617 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 659 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
618 | pub bounds: Box<[TypeBound]>, | 660 | pub bounds: Box<[TypeBound]>, |
619 | pub generic_params: GenericParamsId, | 661 | pub generic_params: GenericParamsId, |
620 | pub type_ref: Option<TypeRef>, | 662 | pub type_ref: Option<Idx<TypeRef>>, |
621 | pub is_extern: bool, | 663 | pub is_extern: bool, |
622 | pub ast_id: FileAstId<ast::TypeAlias>, | 664 | pub ast_id: FileAstId<ast::TypeAlias>, |
623 | } | 665 | } |
@@ -800,6 +842,6 @@ pub enum Fields { | |||
800 | #[derive(Debug, Clone, PartialEq, Eq)] | 842 | #[derive(Debug, Clone, PartialEq, Eq)] |
801 | pub struct Field { | 843 | pub struct Field { |
802 | pub name: Name, | 844 | pub name: Name, |
803 | pub type_ref: TypeRef, | 845 | pub type_ref: Idx<TypeRef>, |
804 | pub visibility: RawVisibilityId, | 846 | pub visibility: RawVisibilityId, |
805 | } | 847 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5e71ca42c..8f2f0b340 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId} | |||
6 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast::{self, ModuleItemOwner}, | 8 | ast::{self, ModuleItemOwner}, |
9 | SyntaxNode, | 9 | SyntaxNode, WalkEvent, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -37,19 +37,17 @@ pub(super) struct Ctx { | |||
37 | file: HirFileId, | 37 | file: HirFileId, |
38 | source_ast_id_map: Arc<AstIdMap>, | 38 | source_ast_id_map: Arc<AstIdMap>, |
39 | body_ctx: crate::body::LowerCtx, | 39 | body_ctx: crate::body::LowerCtx, |
40 | inner_items: Vec<ModItem>, | ||
41 | forced_visibility: Option<RawVisibilityId>, | 40 | forced_visibility: Option<RawVisibilityId>, |
42 | } | 41 | } |
43 | 42 | ||
44 | impl Ctx { | 43 | impl Ctx { |
45 | pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { | 44 | pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { |
46 | Self { | 45 | Self { |
47 | tree: ItemTree::empty(), | 46 | tree: ItemTree::default(), |
48 | hygiene, | 47 | hygiene, |
49 | file, | 48 | file, |
50 | source_ast_id_map: db.ast_id_map(file), | 49 | source_ast_id_map: db.ast_id_map(file), |
51 | body_ctx: crate::body::LowerCtx::new(db, file), | 50 | body_ctx: crate::body::LowerCtx::new(db, file), |
52 | inner_items: Vec::new(), | ||
53 | forced_visibility: None, | 51 | forced_visibility: None, |
54 | } | 52 | } |
55 | } | 53 | } |
@@ -63,6 +61,32 @@ impl Ctx { | |||
63 | self.tree | 61 | self.tree |
64 | } | 62 | } |
65 | 63 | ||
64 | pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree { | ||
65 | self.tree.top_level = stmts | ||
66 | .statements() | ||
67 | .filter_map(|stmt| match stmt { | ||
68 | ast::Stmt::Item(item) => Some(item), | ||
69 | _ => None, | ||
70 | }) | ||
71 | .flat_map(|item| self.lower_mod_item(&item, false)) | ||
72 | .flat_map(|items| items.0) | ||
73 | .collect(); | ||
74 | |||
75 | // Non-items need to have their inner items collected. | ||
76 | for stmt in stmts.statements() { | ||
77 | match stmt { | ||
78 | ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => { | ||
79 | self.collect_inner_items(stmt.syntax()) | ||
80 | } | ||
81 | _ => {} | ||
82 | } | ||
83 | } | ||
84 | if let Some(expr) = stmts.expr() { | ||
85 | self.collect_inner_items(expr.syntax()); | ||
86 | } | ||
87 | self.tree | ||
88 | } | ||
89 | |||
66 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { | 90 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { |
67 | self.collect_inner_items(within); | 91 | self.collect_inner_items(within); |
68 | self.tree | 92 | self.tree |
@@ -73,8 +97,6 @@ impl Ctx { | |||
73 | } | 97 | } |
74 | 98 | ||
75 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { | 99 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { |
76 | assert!(inner || self.inner_items.is_empty()); | ||
77 | |||
78 | // Collect inner items for 1-to-1-lowered items. | 100 | // Collect inner items for 1-to-1-lowered items. |
79 | match item { | 101 | match item { |
80 | ast::Item::Struct(_) | 102 | ast::Item::Struct(_) |
@@ -150,14 +172,38 @@ impl Ctx { | |||
150 | 172 | ||
151 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 173 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
152 | let forced_vis = self.forced_visibility.take(); | 174 | let forced_vis = self.forced_visibility.take(); |
153 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 175 | |
154 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( | 176 | let mut block_stack = Vec::new(); |
155 | |item| { | 177 | for event in container.preorder().skip(1) { |
156 | let ast_id = self.source_ast_id_map.ast_id(&item); | 178 | match event { |
157 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 179 | WalkEvent::Enter(node) => { |
158 | }, | 180 | match_ast! { |
159 | )); | 181 | match node { |
160 | self.tree.inner_items = inner_items; | 182 | ast::BlockExpr(block) => { |
183 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | ||
184 | }, | ||
185 | ast::Item(item) => { | ||
186 | // FIXME: This triggers for macro calls in expression position | ||
187 | let mod_items = self.lower_mod_item(&item, true); | ||
188 | let current_block = block_stack.last(); | ||
189 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
190 | if !mod_items.0.is_empty() { | ||
191 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
192 | } | ||
193 | } | ||
194 | }, | ||
195 | _ => {} | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | WalkEvent::Leave(node) => { | ||
200 | if ast::BlockExpr::cast(node).is_some() { | ||
201 | block_stack.pop(); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
161 | self.forced_visibility = forced_vis; | 207 | self.forced_visibility = forced_vis; |
162 | } | 208 | } |
163 | 209 | ||
@@ -318,6 +364,7 @@ impl Ctx { | |||
318 | params.push(type_ref); | 364 | params.push(type_ref); |
319 | } | 365 | } |
320 | } | 366 | } |
367 | let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect(); | ||
321 | 368 | ||
322 | let mut is_varargs = false; | 369 | let mut is_varargs = false; |
323 | if let Some(params) = func.param_list() { | 370 | if let Some(params) = func.param_list() { |
@@ -339,6 +386,8 @@ impl Ctx { | |||
339 | ret_type | 386 | ret_type |
340 | }; | 387 | }; |
341 | 388 | ||
389 | let ret_type = self.data().type_refs.intern(ret_type); | ||
390 | |||
342 | let has_body = func.body().is_some(); | 391 | let has_body = func.body().is_some(); |
343 | 392 | ||
344 | let ast_id = self.source_ast_id_map.ast_id(func); | 393 | let ast_id = self.source_ast_id_map.ast_id(func); |
@@ -350,7 +399,7 @@ impl Ctx { | |||
350 | has_body, | 399 | has_body, |
351 | is_unsafe: func.unsafe_token().is_some(), | 400 | is_unsafe: func.unsafe_token().is_some(), |
352 | is_extern: false, | 401 | is_extern: false, |
353 | params: params.into_boxed_slice(), | 402 | params, |
354 | is_varargs, | 403 | is_varargs, |
355 | ret_type, | 404 | ret_type, |
356 | ast_id, | 405 | ast_id, |
@@ -611,6 +660,7 @@ impl Ctx { | |||
611 | generics.fill(&self.body_ctx, sm, node); | 660 | generics.fill(&self.body_ctx, sm, node); |
612 | // lower `impl Trait` in arguments | 661 | // lower `impl Trait` in arguments |
613 | for param in &*func.params { | 662 | for param in &*func.params { |
663 | let param = self.data().type_refs.lookup(*param); | ||
614 | generics.fill_implicit_impl_trait_args(param); | 664 | generics.fill_implicit_impl_trait_args(param); |
615 | } | 665 | } |
616 | } | 666 | } |
@@ -663,11 +713,15 @@ impl Ctx { | |||
663 | self.data().vis.alloc(vis) | 713 | self.data().vis.alloc(vis) |
664 | } | 714 | } |
665 | 715 | ||
666 | fn lower_type_ref(&self, type_ref: &ast::Type) -> TypeRef { | 716 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { |
667 | TypeRef::from_ast(&self.body_ctx, type_ref.clone()) | 717 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); |
718 | self.data().type_refs.intern(tyref) | ||
668 | } | 719 | } |
669 | fn lower_type_ref_opt(&self, type_ref: Option<ast::Type>) -> TypeRef { | 720 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { |
670 | type_ref.map(|ty| self.lower_type_ref(&ty)).unwrap_or(TypeRef::Error) | 721 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { |
722 | Some(it) => it, | ||
723 | None => self.data().type_refs.intern(TypeRef::Error), | ||
724 | } | ||
671 | } | 725 | } |
672 | 726 | ||
673 | /// Forces the visibility `vis` to be used for all items lowered during execution of `f`. | 727 | /// Forces the visibility `vis` to be used for all items lowered during execution of `f`. |
@@ -696,7 +750,8 @@ impl Ctx { | |||
696 | 750 | ||
697 | fn desugar_future_path(orig: TypeRef) -> Path { | 751 | fn desugar_future_path(orig: TypeRef) -> Path { |
698 | let path = path![core::future::Future]; | 752 | let path = path![core::future::Future]; |
699 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | 753 | let mut generic_args: Vec<_> = |
754 | std::iter::repeat(None).take(path.segments().len() - 1).collect(); | ||
700 | let mut last = GenericArgs::empty(); | 755 | let mut last = GenericArgs::empty(); |
701 | let binding = | 756 | let binding = |
702 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; | 757 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; |
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 30188b740..9e90f745c 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -84,7 +84,7 @@ impl LangItems { | |||
84 | 84 | ||
85 | let crate_def_map = db.crate_def_map(krate); | 85 | let crate_def_map = db.crate_def_map(krate); |
86 | 86 | ||
87 | for (_, module_data) in crate_def_map.modules.iter() { | 87 | for (_, module_data) in crate_def_map.modules() { |
88 | for impl_def in module_data.scope.impls() { | 88 | for impl_def in module_data.scope.impls() { |
89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) | 89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) |
90 | } | 90 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 08ed920c6..4498d94bb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -50,14 +50,20 @@ pub mod import_map; | |||
50 | #[cfg(test)] | 50 | #[cfg(test)] |
51 | mod test_db; | 51 | mod test_db; |
52 | 52 | ||
53 | use std::hash::{Hash, Hasher}; | 53 | use std::{ |
54 | hash::{Hash, Hasher}, | ||
55 | sync::Arc, | ||
56 | }; | ||
54 | 57 | ||
55 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
56 | use hir_expand::{ | 59 | use hir_expand::{ |
57 | ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, | 60 | ast_id_map::FileAstId, |
58 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 61 | eager::{expand_eager_macro, ErrorEmitted}, |
62 | hygiene::Hygiene, | ||
63 | AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | ||
59 | }; | 64 | }; |
60 | use la_arena::Idx; | 65 | use la_arena::Idx; |
66 | use nameres::DefMap; | ||
61 | use syntax::ast; | 67 | use syntax::ast; |
62 | 68 | ||
63 | use crate::builtin_type::BuiltinType; | 69 | use crate::builtin_type::BuiltinType; |
@@ -69,10 +75,34 @@ use stdx::impl_from; | |||
69 | 75 | ||
70 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 76 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
71 | pub struct ModuleId { | 77 | pub struct ModuleId { |
72 | pub krate: CrateId, | 78 | krate: CrateId, |
79 | block: Option<BlockId>, | ||
73 | pub local_id: LocalModuleId, | 80 | pub local_id: LocalModuleId, |
74 | } | 81 | } |
75 | 82 | ||
83 | impl ModuleId { | ||
84 | pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { | ||
85 | match self.block { | ||
86 | Some(block) => { | ||
87 | db.block_def_map(block).unwrap_or_else(|| { | ||
88 | // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s, | ||
89 | // so the `DefMap` here must exist. | ||
90 | panic!("no `block_def_map` for `ModuleId` {:?}", self); | ||
91 | }) | ||
92 | } | ||
93 | None => db.crate_def_map(self.krate), | ||
94 | } | ||
95 | } | ||
96 | |||
97 | pub fn krate(&self) -> CrateId { | ||
98 | self.krate | ||
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 | } | ||
104 | } | ||
105 | |||
76 | /// An ID of a module, **local** to a specific crate | 106 | /// An ID of a module, **local** to a specific crate |
77 | pub type LocalModuleId = Idx<nameres::ModuleData>; | 107 | pub type LocalModuleId = Idx<nameres::ModuleData>; |
78 | 108 | ||
@@ -216,6 +246,16 @@ pub struct ImplId(salsa::InternId); | |||
216 | type ImplLoc = ItemLoc<Impl>; | 246 | type ImplLoc = ItemLoc<Impl>; |
217 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | 247 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); |
218 | 248 | ||
249 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
250 | pub struct BlockId(salsa::InternId); | ||
251 | #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||
252 | pub struct BlockLoc { | ||
253 | ast_id: AstId<ast::BlockExpr>, | ||
254 | /// The containing module. | ||
255 | module: ModuleId, | ||
256 | } | ||
257 | impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); | ||
258 | |||
219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 259 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
220 | pub struct TypeParamId { | 260 | pub struct TypeParamId { |
221 | pub parent: GenericDefId, | 261 | pub parent: GenericDefId, |
@@ -493,6 +533,25 @@ impl HasModule for StaticLoc { | |||
493 | } | 533 | } |
494 | } | 534 | } |
495 | 535 | ||
536 | impl ModuleDefId { | ||
537 | /// Returns the module containing `self` (or `self`, if `self` is itself a module). | ||
538 | /// | ||
539 | /// Returns `None` if `self` refers to a primitive type. | ||
540 | pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
541 | Some(match self { | ||
542 | ModuleDefId::ModuleId(id) => *id, | ||
543 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), | ||
544 | ModuleDefId::AdtId(id) => id.module(db), | ||
545 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db), | ||
546 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), | ||
547 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db), | ||
548 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db), | ||
549 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), | ||
550 | ModuleDefId::BuiltinType(_) => return None, | ||
551 | }) | ||
552 | } | ||
553 | } | ||
554 | |||
496 | impl AttrDefId { | 555 | impl AttrDefId { |
497 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { | 556 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { |
498 | match self { | 557 | match self { |
@@ -558,8 +617,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
558 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); | 617 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); |
559 | } | 618 | } |
560 | 619 | ||
561 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) | 620 | macro_call_as_call_id( |
562 | .as_call_id_with_errors(db, krate, resolver, error_sink) | 621 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?), |
622 | db, | ||
623 | krate, | ||
624 | resolver, | ||
625 | error_sink, | ||
626 | ) | ||
627 | .ok()? | ||
628 | .ok() | ||
563 | } | 629 | } |
564 | } | 630 | } |
565 | 631 | ||
@@ -576,61 +642,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
576 | } | 642 | } |
577 | } | 643 | } |
578 | 644 | ||
579 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | 645 | struct UnresolvedMacro; |
580 | fn as_call_id_with_errors( | 646 | |
581 | &self, | 647 | fn macro_call_as_call_id( |
582 | db: &dyn db::DefDatabase, | 648 | call: &AstIdWithPath<ast::MacroCall>, |
583 | krate: CrateId, | 649 | db: &dyn db::DefDatabase, |
584 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 650 | krate: CrateId, |
585 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 651 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
586 | ) -> Option<MacroCallId> { | 652 | error_sink: &mut dyn FnMut(mbe::ExpandError), |
587 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | 653 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
588 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | 654 | let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?; |
589 | None | 655 | |
590 | })?; | 656 | let res = if let MacroDefKind::BuiltInEager(_) = def.kind { |
591 | 657 | let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast())); | |
592 | if let MacroDefKind::BuiltInEager(_) = def.kind { | 658 | let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id); |
593 | let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); | 659 | |
594 | let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); | 660 | expand_eager_macro( |
595 | 661 | db.upcast(), | |
596 | Some( | 662 | krate, |
597 | expand_eager_macro( | 663 | macro_call, |
598 | db.upcast(), | 664 | def, |
599 | krate, | 665 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), |
600 | macro_call, | 666 | error_sink, |
601 | def, | ||
602 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), | ||
603 | error_sink, | ||
604 | ) | ||
605 | .ok()? | ||
606 | .into(), | ||
607 | ) | ||
608 | } else { | ||
609 | Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into()) | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | impl AsMacroCall for AstIdWithPath<ast::Item> { | ||
615 | fn as_call_id_with_errors( | ||
616 | &self, | ||
617 | db: &dyn db::DefDatabase, | ||
618 | krate: CrateId, | ||
619 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
620 | error_sink: &mut dyn FnMut(mbe::ExpandError), | ||
621 | ) -> Option<MacroCallId> { | ||
622 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | ||
623 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | ||
624 | None | ||
625 | })?; | ||
626 | |||
627 | Some( | ||
628 | def.as_lazy_macro( | ||
629 | db.upcast(), | ||
630 | krate, | ||
631 | MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()), | ||
632 | ) | ||
633 | .into(), | ||
634 | ) | 667 | ) |
635 | } | 668 | .map(MacroCallId::from) |
669 | } else { | ||
670 | Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) | ||
671 | }; | ||
672 | Ok(res) | ||
673 | } | ||
674 | |||
675 | fn item_attr_as_call_id( | ||
676 | item_attr: &AstIdWithPath<ast::Item>, | ||
677 | db: &dyn db::DefDatabase, | ||
678 | krate: CrateId, | ||
679 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
680 | ) -> Result<MacroCallId, UnresolvedMacro> { | ||
681 | let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?; | ||
682 | let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?; | ||
683 | let res = def | ||
684 | .as_lazy_macro( | ||
685 | db.upcast(), | ||
686 | krate, | ||
687 | MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()), | ||
688 | ) | ||
689 | .into(); | ||
690 | Ok(res) | ||
636 | } | 691 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 50acc3f54..003d668ca 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -59,6 +59,7 @@ use std::sync::Arc; | |||
59 | use base_db::{CrateId, Edition, FileId}; | 59 | use base_db::{CrateId, Edition, FileId}; |
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use la_arena::Arena; | 61 | use la_arena::Arena; |
62 | use profile::Count; | ||
62 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
63 | use stdx::format_to; | 64 | use stdx::format_to; |
64 | use syntax::ast; | 65 | use syntax::ast; |
@@ -69,26 +70,45 @@ use crate::{ | |||
69 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, | 70 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, |
70 | path::ModPath, | 71 | path::ModPath, |
71 | per_ns::PerNs, | 72 | per_ns::PerNs, |
72 | AstId, LocalModuleId, ModuleDefId, ModuleId, | 73 | AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, |
73 | }; | 74 | }; |
74 | 75 | ||
75 | /// Contains all top-level defs from a macro-expanded crate | 76 | /// Contains the results of (early) name resolution. |
77 | /// | ||
78 | /// A `DefMap` stores the module tree and the definitions that are in scope in every module after | ||
79 | /// item-level macros have been expanded. | ||
80 | /// | ||
81 | /// Every crate has a primary `DefMap` whose root is the crate's main file (`main.rs`/`lib.rs`), | ||
82 | /// computed by the `crate_def_map` query. Additionally, every block expression introduces the | ||
83 | /// opportunity to write arbitrary item and module hierarchies, and thus gets its own `DefMap` that | ||
84 | /// is computed by the `block_def_map` query. | ||
76 | #[derive(Debug, PartialEq, Eq)] | 85 | #[derive(Debug, PartialEq, Eq)] |
77 | pub struct CrateDefMap { | 86 | pub struct DefMap { |
78 | pub root: LocalModuleId, | 87 | _c: Count<Self>, |
79 | pub modules: Arena<ModuleData>, | 88 | block: Option<BlockInfo>, |
80 | pub(crate) krate: CrateId, | 89 | root: LocalModuleId, |
90 | modules: Arena<ModuleData>, | ||
91 | krate: CrateId, | ||
81 | /// The prelude module for this crate. This either comes from an import | 92 | /// The prelude module for this crate. This either comes from an import |
82 | /// marked with the `prelude_import` attribute, or (in the normal case) from | 93 | /// marked with the `prelude_import` attribute, or (in the normal case) from |
83 | /// a dependency (`std` or `core`). | 94 | /// a dependency (`std` or `core`). |
84 | pub(crate) prelude: Option<ModuleId>, | 95 | prelude: Option<ModuleId>, |
85 | pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>, | 96 | extern_prelude: FxHashMap<Name, ModuleDefId>, |
86 | 97 | ||
87 | edition: Edition, | 98 | edition: Edition, |
88 | diagnostics: Vec<DefDiagnostic>, | 99 | diagnostics: Vec<DefDiagnostic>, |
89 | } | 100 | } |
90 | 101 | ||
91 | impl std::ops::Index<LocalModuleId> for CrateDefMap { | 102 | /// For `DefMap`s computed for a block expression, this stores its location in the parent map. |
103 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
104 | struct BlockInfo { | ||
105 | /// The `BlockId` this `DefMap` was created from. | ||
106 | block: BlockId, | ||
107 | /// The containing module. | ||
108 | parent: ModuleId, | ||
109 | } | ||
110 | |||
111 | impl std::ops::Index<LocalModuleId> for DefMap { | ||
92 | type Output = ModuleData; | 112 | type Output = ModuleData; |
93 | fn index(&self, id: LocalModuleId) -> &ModuleData { | 113 | fn index(&self, id: LocalModuleId) -> &ModuleData { |
94 | &self.modules[id] | 114 | &self.modules[id] |
@@ -109,6 +129,10 @@ pub enum ModuleOrigin { | |||
109 | Inline { | 129 | Inline { |
110 | definition: AstId<ast::Module>, | 130 | definition: AstId<ast::Module>, |
111 | }, | 131 | }, |
132 | /// Pseudo-module introduced by a block scope (contains only inner items). | ||
133 | BlockExpr { | ||
134 | block: AstId<ast::BlockExpr>, | ||
135 | }, | ||
112 | } | 136 | } |
113 | 137 | ||
114 | impl Default for ModuleOrigin { | 138 | impl Default for ModuleOrigin { |
@@ -122,7 +146,7 @@ impl ModuleOrigin { | |||
122 | match self { | 146 | match self { |
123 | ModuleOrigin::File { declaration: module, .. } | 147 | ModuleOrigin::File { declaration: module, .. } |
124 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), | 148 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), |
125 | ModuleOrigin::CrateRoot { .. } => None, | 149 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, |
126 | } | 150 | } |
127 | } | 151 | } |
128 | 152 | ||
@@ -137,7 +161,7 @@ impl ModuleOrigin { | |||
137 | 161 | ||
138 | pub fn is_inline(&self) -> bool { | 162 | pub fn is_inline(&self) -> bool { |
139 | match self { | 163 | match self { |
140 | ModuleOrigin::Inline { .. } => true, | 164 | ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true, |
141 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, | 165 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, |
142 | } | 166 | } |
143 | } | 167 | } |
@@ -155,6 +179,9 @@ impl ModuleOrigin { | |||
155 | definition.file_id, | 179 | definition.file_id, |
156 | ModuleSource::Module(definition.to_node(db.upcast())), | 180 | ModuleSource::Module(definition.to_node(db.upcast())), |
157 | ), | 181 | ), |
182 | ModuleOrigin::BlockExpr { block } => { | ||
183 | InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast()))) | ||
184 | } | ||
158 | } | 185 | } |
159 | } | 186 | } |
160 | } | 187 | } |
@@ -169,29 +196,54 @@ pub struct ModuleData { | |||
169 | pub origin: ModuleOrigin, | 196 | pub origin: ModuleOrigin, |
170 | } | 197 | } |
171 | 198 | ||
172 | impl CrateDefMap { | 199 | impl DefMap { |
173 | pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 200 | pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> { |
174 | let _p = profile::span("crate_def_map_query").detail(|| { | 201 | let _p = profile::span("crate_def_map_query").detail(|| { |
175 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() | 202 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() |
176 | }); | 203 | }); |
177 | let def_map = { | 204 | let edition = db.crate_graph()[krate].edition; |
178 | let edition = db.crate_graph()[krate].edition; | 205 | let def_map = DefMap::empty(krate, edition); |
179 | let mut modules: Arena<ModuleData> = Arena::default(); | 206 | let def_map = collector::collect_defs(db, def_map, None); |
180 | let root = modules.alloc(ModuleData::default()); | ||
181 | CrateDefMap { | ||
182 | krate, | ||
183 | edition, | ||
184 | extern_prelude: FxHashMap::default(), | ||
185 | prelude: None, | ||
186 | root, | ||
187 | modules, | ||
188 | diagnostics: Vec::new(), | ||
189 | } | ||
190 | }; | ||
191 | let def_map = collector::collect_defs(db, def_map); | ||
192 | Arc::new(def_map) | 207 | Arc::new(def_map) |
193 | } | 208 | } |
194 | 209 | ||
210 | pub(crate) fn block_def_map_query( | ||
211 | db: &dyn DefDatabase, | ||
212 | block_id: BlockId, | ||
213 | ) -> Option<Arc<DefMap>> { | ||
214 | let block: BlockLoc = db.lookup_intern_block(block_id); | ||
215 | |||
216 | let item_tree = db.item_tree(block.ast_id.file_id); | ||
217 | if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { | ||
218 | return None; | ||
219 | } | ||
220 | |||
221 | let block_info = BlockInfo { block: block_id, parent: block.module }; | ||
222 | |||
223 | let parent_map = block.module.def_map(db); | ||
224 | let mut def_map = DefMap::empty(block.module.krate, parent_map.edition); | ||
225 | def_map.block = Some(block_info); | ||
226 | |||
227 | let def_map = collector::collect_defs(db, def_map, Some(block.ast_id)); | ||
228 | Some(Arc::new(def_map)) | ||
229 | } | ||
230 | |||
231 | fn empty(krate: CrateId, edition: Edition) -> DefMap { | ||
232 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
233 | let root = modules.alloc(ModuleData::default()); | ||
234 | DefMap { | ||
235 | _c: Count::new(), | ||
236 | block: None, | ||
237 | krate, | ||
238 | edition, | ||
239 | extern_prelude: FxHashMap::default(), | ||
240 | prelude: None, | ||
241 | root, | ||
242 | modules, | ||
243 | diagnostics: Vec::new(), | ||
244 | } | ||
245 | } | ||
246 | |||
195 | pub fn add_diagnostics( | 247 | pub fn add_diagnostics( |
196 | &self, | 248 | &self, |
197 | db: &dyn DefDatabase, | 249 | db: &dyn DefDatabase, |
@@ -208,6 +260,46 @@ impl CrateDefMap { | |||
208 | .map(|(id, _data)| id) | 260 | .map(|(id, _data)| id) |
209 | } | 261 | } |
210 | 262 | ||
263 | pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ { | ||
264 | self.modules.iter() | ||
265 | } | ||
266 | |||
267 | pub fn root(&self) -> LocalModuleId { | ||
268 | self.root | ||
269 | } | ||
270 | |||
271 | pub(crate) fn krate(&self) -> CrateId { | ||
272 | self.krate | ||
273 | } | ||
274 | |||
275 | pub(crate) fn block_id(&self) -> Option<BlockId> { | ||
276 | self.block.as_ref().map(|block| block.block) | ||
277 | } | ||
278 | |||
279 | pub(crate) fn prelude(&self) -> Option<ModuleId> { | ||
280 | self.prelude | ||
281 | } | ||
282 | |||
283 | pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, &ModuleDefId)> + '_ { | ||
284 | self.extern_prelude.iter() | ||
285 | } | ||
286 | |||
287 | pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { | ||
288 | let block = self.block.as_ref().map(|b| b.block); | ||
289 | ModuleId { krate: self.krate, local_id, block } | ||
290 | } | ||
291 | |||
292 | pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId { | ||
293 | self.with_ancestor_maps(db, self.root, &mut |def_map, _module| { | ||
294 | if def_map.block.is_none() { | ||
295 | Some(def_map.module_id(def_map.root)) | ||
296 | } else { | ||
297 | None | ||
298 | } | ||
299 | }) | ||
300 | .expect("DefMap chain without root") | ||
301 | } | ||
302 | |||
211 | pub(crate) fn resolve_path( | 303 | pub(crate) fn resolve_path( |
212 | &self, | 304 | &self, |
213 | db: &dyn DefDatabase, | 305 | db: &dyn DefDatabase, |
@@ -220,37 +312,68 @@ impl CrateDefMap { | |||
220 | (res.resolved_def, res.segment_index) | 312 | (res.resolved_def, res.segment_index) |
221 | } | 313 | } |
222 | 314 | ||
315 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. | ||
316 | /// | ||
317 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns | ||
318 | /// `None`, iteration continues. | ||
319 | pub fn with_ancestor_maps<T>( | ||
320 | &self, | ||
321 | db: &dyn DefDatabase, | ||
322 | local_mod: LocalModuleId, | ||
323 | f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>, | ||
324 | ) -> Option<T> { | ||
325 | if let Some(it) = f(self, local_mod) { | ||
326 | return Some(it); | ||
327 | } | ||
328 | let mut block = self.block; | ||
329 | while let Some(block_info) = block { | ||
330 | let parent = block_info.parent.def_map(db); | ||
331 | if let Some(it) = f(&parent, block_info.parent.local_id) { | ||
332 | return Some(it); | ||
333 | } | ||
334 | block = parent.block; | ||
335 | } | ||
336 | |||
337 | None | ||
338 | } | ||
339 | |||
340 | /// If this `DefMap` is for a block expression, returns the module containing the block (which | ||
341 | /// might again be a block, or a module inside a block). | ||
342 | pub fn parent(&self) -> Option<ModuleId> { | ||
343 | Some(self.block?.parent) | ||
344 | } | ||
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 | |||
223 | // 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 |
224 | // even), as this should be a great debugging aid. | 359 | // even), as this should be a great debugging aid. |
225 | pub fn dump(&self) -> String { | 360 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
226 | let mut buf = String::new(); | 361 | let mut buf = String::new(); |
227 | go(&mut buf, self, "crate", self.root); | 362 | let mut arc; |
363 | let mut current_map = self; | ||
364 | while let Some(block) = ¤t_map.block { | ||
365 | go(&mut buf, current_map, "block scope", current_map.root); | ||
366 | buf.push('\n'); | ||
367 | arc = block.parent.def_map(db); | ||
368 | current_map = &*arc; | ||
369 | } | ||
370 | go(&mut buf, current_map, "crate", current_map.root); | ||
228 | return buf; | 371 | return buf; |
229 | 372 | ||
230 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { | 373 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { |
231 | format_to!(buf, "{}\n", path); | 374 | format_to!(buf, "{}\n", path); |
232 | 375 | ||
233 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); | 376 | map.modules[module].scope.dump(buf); |
234 | entries.sort_by_key(|(name, _)| name.clone()); | ||
235 | |||
236 | for (name, def) in entries { | ||
237 | format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string())); | ||
238 | |||
239 | if def.types.is_some() { | ||
240 | buf.push_str(" t"); | ||
241 | } | ||
242 | if def.values.is_some() { | ||
243 | buf.push_str(" v"); | ||
244 | } | ||
245 | if def.macros.is_some() { | ||
246 | buf.push_str(" m"); | ||
247 | } | ||
248 | if def.is_none() { | ||
249 | buf.push_str(" _"); | ||
250 | } | ||
251 | |||
252 | buf.push('\n'); | ||
253 | } | ||
254 | 377 | ||
255 | for (name, child) in map.modules[module].children.iter() { | 378 | for (name, child) in map.modules[module].children.iter() { |
256 | let path = format!("{}::{}", path, name); | 379 | let path = format!("{}::{}", path, name); |
@@ -280,6 +403,7 @@ impl ModuleData { | |||
280 | pub enum ModuleSource { | 403 | pub enum ModuleSource { |
281 | SourceFile(ast::SourceFile), | 404 | SourceFile(ast::SourceFile), |
282 | Module(ast::Module), | 405 | Module(ast::Module), |
406 | BlockExpr(ast::BlockExpr), | ||
283 | } | 407 | } |
284 | 408 | ||
285 | mod diagnostics { | 409 | mod diagnostics { |
@@ -305,6 +429,8 @@ mod diagnostics { | |||
305 | 429 | ||
306 | UnresolvedProcMacro { ast: MacroCallKind }, | 430 | UnresolvedProcMacro { ast: MacroCallKind }, |
307 | 431 | ||
432 | UnresolvedMacroCall { ast: AstId<ast::MacroCall> }, | ||
433 | |||
308 | MacroError { ast: MacroCallKind, message: String }, | 434 | MacroError { ast: MacroCallKind, message: String }, |
309 | } | 435 | } |
310 | 436 | ||
@@ -365,6 +491,13 @@ mod diagnostics { | |||
365 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } | 491 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } |
366 | } | 492 | } |
367 | 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 | |||
368 | pub(super) fn add_to( | 501 | pub(super) fn add_to( |
369 | &self, | 502 | &self, |
370 | db: &dyn DefDatabase, | 503 | db: &dyn DefDatabase, |
@@ -477,6 +610,11 @@ mod diagnostics { | |||
477 | }); | 610 | }); |
478 | } | 611 | } |
479 | 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 | |||
480 | DiagnosticKind::MacroError { ast, message } => { | 618 | DiagnosticKind::MacroError { ast, message } => { |
481 | let (file, ast) = match ast { | 619 | let (file, ast) = match ast { |
482 | 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 0cd61698c..e51d89b43 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ 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}; |
@@ -24,38 +24,43 @@ use tt::{Leaf, TokenTree}; | |||
24 | use crate::{ | 24 | use crate::{ |
25 | attr::Attrs, | 25 | attr::Attrs, |
26 | db::DefDatabase, | 26 | db::DefDatabase, |
27 | item_attr_as_call_id, | ||
27 | item_scope::{ImportType, PerNsGlobImports}, | 28 | item_scope::{ImportType, PerNsGlobImports}, |
28 | item_tree::{ | 29 | item_tree::{ |
29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, | 30 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, |
30 | StructDefKind, | 31 | StructDefKind, |
31 | }, | 32 | }, |
33 | macro_call_as_call_id, | ||
32 | nameres::{ | 34 | nameres::{ |
33 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 35 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
34 | BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, | 36 | BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, |
35 | }, | 37 | }, |
36 | path::{ImportAlias, ModPath, PathKind}, | 38 | path::{ImportAlias, ModPath, PathKind}, |
37 | per_ns::PerNs, | 39 | per_ns::PerNs, |
38 | visibility::{RawVisibility, Visibility}, | 40 | visibility::{RawVisibility, Visibility}, |
39 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, | 41 | AdtId, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, |
40 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, | 42 | ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, |
41 | TraitLoc, TypeAliasLoc, UnionLoc, | 43 | UnionLoc, UnresolvedMacro, |
42 | }; | 44 | }; |
43 | 45 | ||
44 | const GLOB_RECURSION_LIMIT: usize = 100; | 46 | const GLOB_RECURSION_LIMIT: usize = 100; |
45 | const EXPANSION_DEPTH_LIMIT: usize = 128; | 47 | const EXPANSION_DEPTH_LIMIT: usize = 128; |
46 | const FIXED_POINT_LIMIT: usize = 8192; | 48 | const FIXED_POINT_LIMIT: usize = 8192; |
47 | 49 | ||
48 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 50 | pub(super) fn collect_defs( |
51 | db: &dyn DefDatabase, | ||
52 | mut def_map: DefMap, | ||
53 | block: Option<AstId<ast::BlockExpr>>, | ||
54 | ) -> DefMap { | ||
49 | let crate_graph = db.crate_graph(); | 55 | let crate_graph = db.crate_graph(); |
50 | 56 | ||
51 | // populate external prelude | 57 | // populate external prelude |
52 | for dep in &crate_graph[def_map.krate].dependencies { | 58 | for dep in &crate_graph[def_map.krate].dependencies { |
53 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); | 59 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); |
54 | let dep_def_map = db.crate_def_map(dep.crate_id); | 60 | let dep_def_map = db.crate_def_map(dep.crate_id); |
55 | def_map.extern_prelude.insert( | 61 | def_map |
56 | dep.as_name(), | 62 | .extern_prelude |
57 | ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), | 63 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); |
58 | ); | ||
59 | 64 | ||
60 | // look for the prelude | 65 | // look for the prelude |
61 | // If the dependency defines a prelude, we overwrite an already defined | 66 | // If the dependency defines a prelude, we overwrite an already defined |
@@ -93,6 +98,14 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
93 | exports_proc_macros: false, | 98 | exports_proc_macros: false, |
94 | from_glob_import: Default::default(), | 99 | from_glob_import: Default::default(), |
95 | }; | 100 | }; |
101 | match block { | ||
102 | Some(block) => { | ||
103 | collector.seed_with_inner(block); | ||
104 | } | ||
105 | None => { | ||
106 | collector.seed_with_top_level(); | ||
107 | } | ||
108 | } | ||
96 | collector.collect(); | 109 | collector.collect(); |
97 | collector.finish() | 110 | collector.finish() |
98 | } | 111 | } |
@@ -210,7 +223,7 @@ struct DefData<'a> { | |||
210 | /// Walks the tree of module recursively | 223 | /// Walks the tree of module recursively |
211 | struct DefCollector<'a> { | 224 | struct DefCollector<'a> { |
212 | db: &'a dyn DefDatabase, | 225 | db: &'a dyn DefDatabase, |
213 | def_map: CrateDefMap, | 226 | def_map: DefMap, |
214 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, | 227 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, |
215 | unresolved_imports: Vec<ImportDirective>, | 228 | unresolved_imports: Vec<ImportDirective>, |
216 | resolved_imports: Vec<ImportDirective>, | 229 | resolved_imports: Vec<ImportDirective>, |
@@ -228,7 +241,7 @@ struct DefCollector<'a> { | |||
228 | } | 241 | } |
229 | 242 | ||
230 | impl DefCollector<'_> { | 243 | impl DefCollector<'_> { |
231 | fn collect(&mut self) { | 244 | fn seed_with_top_level(&mut self) { |
232 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | 245 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; |
233 | let item_tree = self.db.item_tree(file_id.into()); | 246 | let item_tree = self.db.item_tree(file_id.into()); |
234 | let module_id = self.def_map.root; | 247 | let module_id = self.def_map.root; |
@@ -248,7 +261,30 @@ impl DefCollector<'_> { | |||
248 | } | 261 | } |
249 | .collect(item_tree.top_level_items()); | 262 | .collect(item_tree.top_level_items()); |
250 | } | 263 | } |
264 | } | ||
251 | 265 | ||
266 | fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) { | ||
267 | let item_tree = self.db.item_tree(block.file_id); | ||
268 | let module_id = self.def_map.root; | ||
269 | self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block }; | ||
270 | if item_tree | ||
271 | .top_level_attrs(self.db, self.def_map.krate) | ||
272 | .cfg() | ||
273 | .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) | ||
274 | { | ||
275 | ModCollector { | ||
276 | def_collector: &mut *self, | ||
277 | macro_depth: 0, | ||
278 | module_id, | ||
279 | file_id: block.file_id, | ||
280 | item_tree: &item_tree, | ||
281 | mod_dir: ModDir::root(), | ||
282 | } | ||
283 | .collect(item_tree.inner_items_of_block(block.value)); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | fn collect(&mut self) { | ||
252 | // main name resolution fixed-point loop. | 288 | // main name resolution fixed-point loop. |
253 | let mut i = 0; | 289 | let mut i = 0; |
254 | loop { | 290 | loop { |
@@ -296,11 +332,9 @@ impl DefCollector<'_> { | |||
296 | // exported in type/value namespace. This function reduces the visibility of all items | 332 | // exported in type/value namespace. This function reduces the visibility of all items |
297 | // in the crate root that aren't proc macros. | 333 | // in the crate root that aren't proc macros. |
298 | let root = self.def_map.root; | 334 | let root = self.def_map.root; |
335 | let module_id = self.def_map.module_id(root); | ||
299 | let root = &mut self.def_map.modules[root]; | 336 | let root = &mut self.def_map.modules[root]; |
300 | root.scope.censor_non_proc_macros(ModuleId { | 337 | root.scope.censor_non_proc_macros(module_id); |
301 | krate: self.def_map.krate, | ||
302 | local_id: self.def_map.root, | ||
303 | }); | ||
304 | } | 338 | } |
305 | } | 339 | } |
306 | 340 | ||
@@ -542,7 +576,7 @@ impl DefCollector<'_> { | |||
542 | } else if m.krate != self.def_map.krate { | 576 | } else if m.krate != self.def_map.krate { |
543 | mark::hit!(glob_across_crates); | 577 | mark::hit!(glob_across_crates); |
544 | // glob import from other crate => we can just import everything once | 578 | // glob import from other crate => we can just import everything once |
545 | let item_map = self.db.crate_def_map(m.krate); | 579 | let item_map = m.def_map(self.db); |
546 | let scope = &item_map[m.local_id].scope; | 580 | let scope = &item_map[m.local_id].scope; |
547 | 581 | ||
548 | // Module scoped macros is included | 582 | // Module scoped macros is included |
@@ -560,7 +594,13 @@ impl DefCollector<'_> { | |||
560 | // glob import from same crate => we do an initial | 594 | // glob import from same crate => we do an initial |
561 | // import, and then need to propagate any further | 595 | // import, and then need to propagate any further |
562 | // additions | 596 | // additions |
563 | let scope = &self.def_map[m.local_id].scope; | 597 | let def_map; |
598 | let scope = if m.block == self.def_map.block_id() { | ||
599 | &self.def_map[m.local_id].scope | ||
600 | } else { | ||
601 | def_map = m.def_map(self.db); | ||
602 | &def_map[m.local_id].scope | ||
603 | }; | ||
564 | 604 | ||
565 | // Module scoped macros is included | 605 | // Module scoped macros is included |
566 | let items = scope | 606 | let items = scope |
@@ -570,7 +610,7 @@ impl DefCollector<'_> { | |||
570 | ( | 610 | ( |
571 | n, | 611 | n, |
572 | res.filter_visibility(|v| { | 612 | res.filter_visibility(|v| { |
573 | v.is_visible_from_def_map(&self.def_map, module_id) | 613 | v.is_visible_from_def_map(self.db, &self.def_map, module_id) |
574 | }), | 614 | }), |
575 | ) | 615 | ) |
576 | }) | 616 | }) |
@@ -617,7 +657,7 @@ impl DefCollector<'_> { | |||
617 | } | 657 | } |
618 | } | 658 | } |
619 | } else { | 659 | } else { |
620 | match import.path.segments.last() { | 660 | match import.path.segments().last() { |
621 | Some(last_segment) => { | 661 | Some(last_segment) => { |
622 | let name = match &import.alias { | 662 | let name = match &import.alias { |
623 | Some(ImportAlias::Alias(name)) => Some(name.clone()), | 663 | Some(ImportAlias::Alias(name)) => Some(name.clone()), |
@@ -723,7 +763,7 @@ impl DefCollector<'_> { | |||
723 | .filter(|(glob_importing_module, _)| { | 763 | .filter(|(glob_importing_module, _)| { |
724 | // we know all resolutions have the same visibility (`vis`), so we | 764 | // we know all resolutions have the same visibility (`vis`), so we |
725 | // just need to check that once | 765 | // just need to check that once |
726 | vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) | 766 | vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module) |
727 | }) | 767 | }) |
728 | .cloned() | 768 | .cloned() |
729 | .collect::<Vec<_>>(); | 769 | .collect::<Vec<_>>(); |
@@ -752,8 +792,11 @@ impl DefCollector<'_> { | |||
752 | return false; | 792 | return false; |
753 | } | 793 | } |
754 | 794 | ||
755 | if let Some(call_id) = | 795 | match macro_call_as_call_id( |
756 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 796 | &directive.ast_id, |
797 | self.db, | ||
798 | self.def_map.krate, | ||
799 | |path| { | ||
757 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 800 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
758 | self.db, | 801 | self.db, |
759 | ResolveMode::Other, | 802 | ResolveMode::Other, |
@@ -762,24 +805,29 @@ impl DefCollector<'_> { | |||
762 | BuiltinShadowMode::Module, | 805 | BuiltinShadowMode::Module, |
763 | ); | 806 | ); |
764 | resolved_res.resolved_def.take_macros() | 807 | resolved_res.resolved_def.take_macros() |
765 | }) | 808 | }, |
766 | { | 809 | &mut |_err| (), |
767 | resolved.push((directive.module_id, call_id, directive.depth)); | 810 | ) { |
768 | res = ReachedFixedPoint::No; | 811 | Ok(Ok(call_id)) => { |
769 | return false; | 812 | resolved.push((directive.module_id, call_id, directive.depth)); |
813 | res = ReachedFixedPoint::No; | ||
814 | return false; | ||
815 | } | ||
816 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | ||
770 | } | 817 | } |
771 | 818 | ||
772 | true | 819 | true |
773 | }); | 820 | }); |
774 | attribute_macros.retain(|directive| { | 821 | attribute_macros.retain(|directive| { |
775 | if let Some(call_id) = | 822 | match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { |
776 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 823 | self.resolve_attribute_macro(&directive, &path) |
777 | self.resolve_attribute_macro(&directive, &path) | 824 | }) { |
778 | }) | 825 | Ok(call_id) => { |
779 | { | 826 | resolved.push((directive.module_id, call_id, 0)); |
780 | resolved.push((directive.module_id, call_id, 0)); | 827 | res = ReachedFixedPoint::No; |
781 | res = ReachedFixedPoint::No; | 828 | return false; |
782 | return false; | 829 | } |
830 | Err(UnresolvedMacro) => (), | ||
783 | } | 831 | } |
784 | 832 | ||
785 | true | 833 | true |
@@ -859,12 +907,13 @@ impl DefCollector<'_> { | |||
859 | .collect(item_tree.top_level_items()); | 907 | .collect(item_tree.top_level_items()); |
860 | } | 908 | } |
861 | 909 | ||
862 | fn finish(mut self) -> CrateDefMap { | 910 | fn finish(mut self) -> DefMap { |
863 | // Emit diagnostics for all remaining unexpanded macros. | 911 | // Emit diagnostics for all remaining unexpanded macros. |
864 | 912 | ||
865 | for directive in &self.unexpanded_macros { | 913 | for directive in &self.unexpanded_macros { |
866 | let mut error = None; | 914 | let mut error = None; |
867 | directive.ast_id.as_call_id_with_errors( | 915 | match macro_call_as_call_id( |
916 | &directive.ast_id, | ||
868 | self.db, | 917 | self.db, |
869 | self.def_map.krate, | 918 | self.def_map.krate, |
870 | |path| { | 919 | |path| { |
@@ -880,15 +929,15 @@ impl DefCollector<'_> { | |||
880 | &mut |e| { | 929 | &mut |e| { |
881 | error.get_or_insert(e); | 930 | error.get_or_insert(e); |
882 | }, | 931 | }, |
883 | ); | 932 | ) { |
884 | 933 | Ok(_) => (), | |
885 | if let Some(err) = error { | 934 | Err(UnresolvedMacro) => { |
886 | self.def_map.diagnostics.push(DefDiagnostic::macro_error( | 935 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( |
887 | directive.module_id, | 936 | directive.module_id, |
888 | MacroCallKind::FnLike(directive.ast_id.ast_id), | 937 | directive.ast_id.ast_id, |
889 | err.to_string(), | 938 | )); |
890 | )); | 939 | } |
891 | } | 940 | }; |
892 | } | 941 | } |
893 | 942 | ||
894 | // Emit diagnostics for all remaining unresolved imports. | 943 | // Emit diagnostics for all remaining unresolved imports. |
@@ -918,7 +967,7 @@ impl DefCollector<'_> { | |||
918 | let item_tree = self.db.item_tree(import.file_id); | 967 | let item_tree = self.db.item_tree(import.file_id); |
919 | let import_data = &item_tree[import.value]; | 968 | let import_data = &item_tree[import.value]; |
920 | 969 | ||
921 | match (import_data.path.segments.first(), &import_data.path.kind) { | 970 | match (import_data.path.segments().first(), &import_data.path.kind) { |
922 | (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { | 971 | (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { |
923 | if diagnosed_extern_crates.contains(krate) { | 972 | if diagnosed_extern_crates.contains(krate) { |
924 | continue; | 973 | continue; |
@@ -993,8 +1042,7 @@ impl ModCollector<'_, '_> { | |||
993 | continue; | 1042 | continue; |
994 | } | 1043 | } |
995 | } | 1044 | } |
996 | let module = | 1045 | let module = self.def_collector.def_map.module_id(self.module_id); |
997 | ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; | ||
998 | let container = ContainerId::ModuleId(module); | 1046 | let container = ContainerId::ModuleId(module); |
999 | 1047 | ||
1000 | let mut def = None; | 1048 | let mut def = None; |
@@ -1061,10 +1109,7 @@ impl ModCollector<'_, '_> { | |||
1061 | } | 1109 | } |
1062 | } | 1110 | } |
1063 | ModItem::Impl(imp) => { | 1111 | ModItem::Impl(imp) => { |
1064 | let module = ModuleId { | 1112 | let module = self.def_collector.def_map.module_id(self.module_id); |
1065 | krate: self.def_collector.def_map.krate, | ||
1066 | local_id: self.module_id, | ||
1067 | }; | ||
1068 | let container = ContainerId::ModuleId(module); | 1113 | let container = ContainerId::ModuleId(module); |
1069 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } | 1114 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } |
1070 | .intern(self.def_collector.db); | 1115 | .intern(self.def_collector.db); |
@@ -1245,12 +1290,8 @@ impl ModCollector<'_, '_> { | |||
1245 | // out of line module, resolve, parse and recurse | 1290 | // out of line module, resolve, parse and recurse |
1246 | ModKind::Outline {} => { | 1291 | ModKind::Outline {} => { |
1247 | let ast_id = AstId::new(self.file_id, module.ast_id); | 1292 | let ast_id = AstId::new(self.file_id, module.ast_id); |
1248 | match self.mod_dir.resolve_declaration( | 1293 | let db = self.def_collector.db; |
1249 | self.def_collector.db, | 1294 | match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) { |
1250 | self.file_id, | ||
1251 | &module.name, | ||
1252 | path_attr, | ||
1253 | ) { | ||
1254 | Ok((file_id, is_mod_rs, mod_dir)) => { | 1295 | Ok((file_id, is_mod_rs, mod_dir)) => { |
1255 | let module_id = self.push_child_module( | 1296 | let module_id = self.push_child_module( |
1256 | module.name.clone(), | 1297 | module.name.clone(), |
@@ -1258,7 +1299,7 @@ impl ModCollector<'_, '_> { | |||
1258 | Some((file_id, is_mod_rs)), | 1299 | Some((file_id, is_mod_rs)), |
1259 | &self.item_tree[module.visibility], | 1300 | &self.item_tree[module.visibility], |
1260 | ); | 1301 | ); |
1261 | let item_tree = self.def_collector.db.item_tree(file_id.into()); | 1302 | let item_tree = db.item_tree(file_id.into()); |
1262 | ModCollector { | 1303 | ModCollector { |
1263 | def_collector: &mut *self.def_collector, | 1304 | def_collector: &mut *self.def_collector, |
1264 | macro_depth: self.macro_depth, | 1305 | macro_depth: self.macro_depth, |
@@ -1268,7 +1309,12 @@ impl ModCollector<'_, '_> { | |||
1268 | mod_dir, | 1309 | mod_dir, |
1269 | } | 1310 | } |
1270 | .collect(item_tree.top_level_items()); | 1311 | .collect(item_tree.top_level_items()); |
1271 | if is_macro_use { | 1312 | if is_macro_use |
1313 | || item_tree | ||
1314 | .top_level_attrs(db, self.def_collector.def_map.krate) | ||
1315 | .by_key("macro_use") | ||
1316 | .exists() | ||
1317 | { | ||
1272 | self.import_all_legacy_macros(module_id); | 1318 | self.import_all_legacy_macros(module_id); |
1273 | } | 1319 | } |
1274 | } | 1320 | } |
@@ -1307,7 +1353,7 @@ impl ModCollector<'_, '_> { | |||
1307 | modules[res].scope.define_legacy_macro(name, mac) | 1353 | modules[res].scope.define_legacy_macro(name, mac) |
1308 | } | 1354 | } |
1309 | modules[self.module_id].children.insert(name.clone(), res); | 1355 | modules[self.module_id].children.insert(name.clone(), res); |
1310 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 1356 | let module = self.def_collector.def_map.module_id(res); |
1311 | let def: ModuleDefId = module.into(); | 1357 | let def: ModuleDefId = module.into(); |
1312 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1358 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1313 | self.def_collector.update( | 1359 | self.def_collector.update( |
@@ -1411,13 +1457,21 @@ impl ModCollector<'_, '_> { | |||
1411 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1457 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
1412 | 1458 | ||
1413 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1459 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1414 | if let Some(macro_call_id) = | 1460 | if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( |
1415 | ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { | 1461 | &ast_id, |
1462 | self.def_collector.db, | ||
1463 | self.def_collector.def_map.krate, | ||
1464 | |path| { | ||
1416 | path.as_ident().and_then(|name| { | 1465 | path.as_ident().and_then(|name| { |
1417 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | 1466 | self.def_collector.def_map.with_ancestor_maps( |
1467 | self.def_collector.db, | ||
1468 | self.module_id, | ||
1469 | &mut |map, module| map[module].scope.get_legacy_macro(&name), | ||
1470 | ) | ||
1418 | }) | 1471 | }) |
1419 | }) | 1472 | }, |
1420 | { | 1473 | &mut |_err| (), |
1474 | ) { | ||
1421 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1475 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1422 | module_id: self.module_id, | 1476 | module_id: self.module_id, |
1423 | ast_id, | 1477 | ast_id, |
@@ -1470,11 +1524,10 @@ impl ModCollector<'_, '_> { | |||
1470 | mod tests { | 1524 | mod tests { |
1471 | use crate::{db::DefDatabase, test_db::TestDB}; | 1525 | use crate::{db::DefDatabase, test_db::TestDB}; |
1472 | use base_db::{fixture::WithFixture, SourceDatabase}; | 1526 | use base_db::{fixture::WithFixture, SourceDatabase}; |
1473 | use la_arena::Arena; | ||
1474 | 1527 | ||
1475 | use super::*; | 1528 | use super::*; |
1476 | 1529 | ||
1477 | fn do_collect_defs(db: &dyn DefDatabase, def_map: CrateDefMap) -> CrateDefMap { | 1530 | fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap { |
1478 | let mut collector = DefCollector { | 1531 | let mut collector = DefCollector { |
1479 | db, | 1532 | db, |
1480 | def_map, | 1533 | def_map, |
@@ -1489,28 +1542,17 @@ mod tests { | |||
1489 | exports_proc_macros: false, | 1542 | exports_proc_macros: false, |
1490 | from_glob_import: Default::default(), | 1543 | from_glob_import: Default::default(), |
1491 | }; | 1544 | }; |
1545 | collector.seed_with_top_level(); | ||
1492 | collector.collect(); | 1546 | collector.collect(); |
1493 | collector.def_map | 1547 | collector.def_map |
1494 | } | 1548 | } |
1495 | 1549 | ||
1496 | fn do_resolve(code: &str) -> CrateDefMap { | 1550 | fn do_resolve(code: &str) -> DefMap { |
1497 | let (db, _file_id) = TestDB::with_single_file(&code); | 1551 | let (db, _file_id) = TestDB::with_single_file(&code); |
1498 | let krate = db.test_crate(); | 1552 | let krate = db.test_crate(); |
1499 | 1553 | ||
1500 | let def_map = { | 1554 | let edition = db.crate_graph()[krate].edition; |
1501 | let edition = db.crate_graph()[krate].edition; | 1555 | let def_map = DefMap::empty(krate, edition); |
1502 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
1503 | let root = modules.alloc(ModuleData::default()); | ||
1504 | CrateDefMap { | ||
1505 | krate, | ||
1506 | edition, | ||
1507 | extern_prelude: FxHashMap::default(), | ||
1508 | prelude: None, | ||
1509 | root, | ||
1510 | modules, | ||
1511 | diagnostics: Vec::new(), | ||
1512 | } | ||
1513 | }; | ||
1514 | do_collect_defs(&db, def_map) | 1556 | do_collect_defs(&db, def_map) |
1515 | } | 1557 | } |
1516 | 1558 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 88e10574e..dd1db0094 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -10,20 +10,19 @@ | |||
10 | //! | 10 | //! |
11 | //! `ReachedFixedPoint` signals about this. | 11 | //! `ReachedFixedPoint` signals about this. |
12 | 12 | ||
13 | use std::iter::successors; | ||
14 | |||
15 | use base_db::Edition; | 13 | use base_db::Edition; |
14 | use hir_expand::name; | ||
16 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
17 | use test_utils::mark; | 16 | use test_utils::mark; |
18 | 17 | ||
19 | use crate::{ | 18 | use crate::{ |
20 | db::DefDatabase, | 19 | db::DefDatabase, |
21 | item_scope::BUILTIN_SCOPE, | 20 | item_scope::BUILTIN_SCOPE, |
22 | nameres::{BuiltinShadowMode, CrateDefMap}, | 21 | nameres::{BuiltinShadowMode, DefMap}, |
23 | path::{ModPath, PathKind}, | 22 | path::{ModPath, PathKind}, |
24 | per_ns::PerNs, | 23 | per_ns::PerNs, |
25 | visibility::{RawVisibility, Visibility}, | 24 | visibility::{RawVisibility, Visibility}, |
26 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, | 25 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, |
27 | }; | 26 | }; |
28 | 27 | ||
29 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 28 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
@@ -61,8 +60,12 @@ impl ResolvePathResult { | |||
61 | } | 60 | } |
62 | } | 61 | } |
63 | 62 | ||
64 | impl CrateDefMap { | 63 | impl DefMap { |
65 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { | 64 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { |
65 | if name == &name!(self) { | ||
66 | mark::hit!(extern_crate_self_as); | ||
67 | return PerNs::types(self.module_id(self.root).into(), Visibility::Public); | ||
68 | } | ||
66 | self.extern_prelude | 69 | self.extern_prelude |
67 | .get(name) | 70 | .get(name) |
68 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) | 71 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) |
@@ -74,7 +77,7 @@ impl CrateDefMap { | |||
74 | original_module: LocalModuleId, | 77 | original_module: LocalModuleId, |
75 | visibility: &RawVisibility, | 78 | visibility: &RawVisibility, |
76 | ) -> Option<Visibility> { | 79 | ) -> Option<Visibility> { |
77 | match visibility { | 80 | let mut vis = match visibility { |
78 | RawVisibility::Module(path) => { | 81 | RawVisibility::Module(path) => { |
79 | let (result, remaining) = | 82 | let (result, remaining) = |
80 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | 83 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); |
@@ -83,15 +86,28 @@ impl CrateDefMap { | |||
83 | } | 86 | } |
84 | let types = result.take_types()?; | 87 | let types = result.take_types()?; |
85 | match types { | 88 | match types { |
86 | ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), | 89 | ModuleDefId::ModuleId(m) => Visibility::Module(m), |
87 | _ => { | 90 | _ => { |
88 | // error: visibility needs to refer to module | 91 | // error: visibility needs to refer to module |
89 | None | 92 | return None; |
90 | } | 93 | } |
91 | } | 94 | } |
92 | } | 95 | } |
93 | RawVisibility::Public => Some(Visibility::Public), | 96 | RawVisibility::Public => Visibility::Public, |
97 | }; | ||
98 | |||
99 | // In block expressions, `self` normally refers to the containing non-block module, and | ||
100 | // `super` to its parent (etc.). However, visibilities must only refer to a module in the | ||
101 | // DefMap they're written in, so we restrict them when that happens. | ||
102 | if let Visibility::Module(m) = vis { | ||
103 | if self.block_id() != m.block { | ||
104 | mark::hit!(adjust_vis_in_block_def_map); | ||
105 | vis = Visibility::Module(self.module_id(self.root())); | ||
106 | log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); | ||
107 | } | ||
94 | } | 108 | } |
109 | |||
110 | Some(vis) | ||
95 | } | 111 | } |
96 | 112 | ||
97 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 113 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
@@ -100,30 +116,69 @@ impl CrateDefMap { | |||
100 | &self, | 116 | &self, |
101 | db: &dyn DefDatabase, | 117 | db: &dyn DefDatabase, |
102 | mode: ResolveMode, | 118 | mode: ResolveMode, |
119 | mut original_module: LocalModuleId, | ||
120 | path: &ModPath, | ||
121 | shadow: BuiltinShadowMode, | ||
122 | ) -> ResolvePathResult { | ||
123 | let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); | ||
124 | |||
125 | let mut arc; | ||
126 | let mut current_map = self; | ||
127 | loop { | ||
128 | let new = current_map.resolve_path_fp_with_macro_single( | ||
129 | db, | ||
130 | mode, | ||
131 | original_module, | ||
132 | path, | ||
133 | shadow, | ||
134 | ); | ||
135 | |||
136 | // Merge `new` into `result`. | ||
137 | result.resolved_def = result.resolved_def.or(new.resolved_def); | ||
138 | if result.reached_fixedpoint == ReachedFixedPoint::No { | ||
139 | result.reached_fixedpoint = new.reached_fixedpoint; | ||
140 | } | ||
141 | // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates? | ||
142 | result.krate = result.krate.or(new.krate); | ||
143 | result.segment_index = match (result.segment_index, new.segment_index) { | ||
144 | (Some(idx), None) => Some(idx), | ||
145 | (Some(old), Some(new)) => Some(old.max(new)), | ||
146 | (None, new) => new, | ||
147 | }; | ||
148 | |||
149 | match ¤t_map.block { | ||
150 | Some(block) => { | ||
151 | original_module = block.parent.local_id; | ||
152 | arc = block.parent.def_map(db); | ||
153 | current_map = &*arc; | ||
154 | } | ||
155 | None => return result, | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | pub(super) fn resolve_path_fp_with_macro_single( | ||
161 | &self, | ||
162 | db: &dyn DefDatabase, | ||
163 | mode: ResolveMode, | ||
103 | original_module: LocalModuleId, | 164 | original_module: LocalModuleId, |
104 | path: &ModPath, | 165 | path: &ModPath, |
105 | shadow: BuiltinShadowMode, | 166 | shadow: BuiltinShadowMode, |
106 | ) -> ResolvePathResult { | 167 | ) -> ResolvePathResult { |
107 | let mut segments = path.segments.iter().enumerate(); | 168 | let mut segments = path.segments().iter().enumerate(); |
108 | let mut curr_per_ns: PerNs = match path.kind { | 169 | let mut curr_per_ns: PerNs = match path.kind { |
109 | PathKind::DollarCrate(krate) => { | 170 | PathKind::DollarCrate(krate) => { |
110 | if krate == self.krate { | 171 | if krate == self.krate { |
111 | mark::hit!(macro_dollar_crate_self); | 172 | mark::hit!(macro_dollar_crate_self); |
112 | PerNs::types( | 173 | PerNs::types(self.crate_root(db).into(), Visibility::Public) |
113 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
114 | Visibility::Public, | ||
115 | ) | ||
116 | } else { | 174 | } else { |
117 | let def_map = db.crate_def_map(krate); | 175 | let def_map = db.crate_def_map(krate); |
118 | let module = ModuleId { krate, local_id: def_map.root }; | 176 | let module = def_map.module_id(def_map.root); |
119 | mark::hit!(macro_dollar_crate_other); | 177 | mark::hit!(macro_dollar_crate_other); |
120 | PerNs::types(module.into(), Visibility::Public) | 178 | PerNs::types(module.into(), Visibility::Public) |
121 | } | 179 | } |
122 | } | 180 | } |
123 | PathKind::Crate => PerNs::types( | 181 | PathKind::Crate => PerNs::types(self.crate_root(db).into(), Visibility::Public), |
124 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
125 | Visibility::Public, | ||
126 | ), | ||
127 | // plain import or absolute path in 2015: crate-relative with | 182 | // plain import or absolute path in 2015: crate-relative with |
128 | // fallback to extern prelude (with the simplification in | 183 | // fallback to extern prelude (with the simplification in |
129 | // rust-lang/rust#57745) | 184 | // rust-lang/rust#57745) |
@@ -151,23 +206,49 @@ impl CrateDefMap { | |||
151 | // BuiltinShadowMode wasn't Module, then we need to try | 206 | // BuiltinShadowMode wasn't Module, then we need to try |
152 | // resolving it as a builtin. | 207 | // resolving it as a builtin. |
153 | let prefer_module = | 208 | let prefer_module = |
154 | if path.segments.len() == 1 { shadow } else { BuiltinShadowMode::Module }; | 209 | if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module }; |
155 | 210 | ||
156 | log::debug!("resolving {:?} in module", segment); | 211 | log::debug!("resolving {:?} in module", segment); |
157 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) | 212 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) |
158 | } | 213 | } |
159 | PathKind::Super(lvl) => { | 214 | PathKind::Super(lvl) => { |
160 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 215 | let mut module = original_module; |
161 | .nth(lvl as usize); | 216 | for i in 0..lvl { |
162 | if let Some(local_id) = m { | 217 | match self.modules[module].parent { |
163 | PerNs::types( | 218 | Some(it) => module = it, |
164 | ModuleId { krate: self.krate, local_id }.into(), | 219 | None => match &self.block { |
165 | Visibility::Public, | 220 | Some(block) => { |
166 | ) | 221 | // Look up remaining path in parent `DefMap` |
167 | } else { | 222 | let new_path = ModPath::from_segments( |
168 | log::debug!("super path in root module"); | 223 | PathKind::Super(lvl - i), |
169 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 224 | path.segments().to_vec(), |
225 | ); | ||
226 | log::debug!("`super` path: {} -> {} in parent map", path, new_path); | ||
227 | return block.parent.def_map(db).resolve_path_fp_with_macro( | ||
228 | db, | ||
229 | mode, | ||
230 | block.parent.local_id, | ||
231 | &new_path, | ||
232 | shadow, | ||
233 | ); | ||
234 | } | ||
235 | None => { | ||
236 | log::debug!("super path in root module"); | ||
237 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | ||
238 | } | ||
239 | }, | ||
240 | } | ||
170 | } | 241 | } |
242 | |||
243 | // Resolve `self` to the containing crate-rooted module if we're a block | ||
244 | self.with_ancestor_maps(db, module, &mut |def_map, module| { | ||
245 | if def_map.block.is_some() { | ||
246 | None // keep ascending | ||
247 | } else { | ||
248 | Some(PerNs::types(def_map.module_id(module).into(), Visibility::Public)) | ||
249 | } | ||
250 | }) | ||
251 | .expect("block DefMap not rooted in crate DefMap") | ||
171 | } | 252 | } |
172 | PathKind::Abs => { | 253 | PathKind::Abs => { |
173 | // 2018-style absolute path -- only extern prelude | 254 | // 2018-style absolute path -- only extern prelude |
@@ -201,12 +282,12 @@ impl CrateDefMap { | |||
201 | curr_per_ns = match curr { | 282 | curr_per_ns = match curr { |
202 | ModuleDefId::ModuleId(module) => { | 283 | ModuleDefId::ModuleId(module) => { |
203 | if module.krate != self.krate { | 284 | if module.krate != self.krate { |
204 | let path = ModPath { | 285 | let path = ModPath::from_segments( |
205 | segments: path.segments[i..].to_vec(), | 286 | PathKind::Super(0), |
206 | kind: PathKind::Super(0), | 287 | path.segments()[i..].iter().cloned(), |
207 | }; | 288 | ); |
208 | log::debug!("resolving {:?} in other crate", path); | 289 | log::debug!("resolving {:?} in other crate", path); |
209 | let defp_map = db.crate_def_map(module.krate); | 290 | let defp_map = module.def_map(db); |
210 | let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); | 291 | let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); |
211 | return ResolvePathResult::with( | 292 | return ResolvePathResult::with( |
212 | def, | 293 | def, |
@@ -216,8 +297,16 @@ impl CrateDefMap { | |||
216 | ); | 297 | ); |
217 | } | 298 | } |
218 | 299 | ||
300 | let def_map; | ||
301 | let module_data = if module.block == self.block_id() { | ||
302 | &self[module.local_id] | ||
303 | } else { | ||
304 | def_map = module.def_map(db); | ||
305 | &def_map[module.local_id] | ||
306 | }; | ||
307 | |||
219 | // Since it is a qualified path here, it should not contains legacy macros | 308 | // Since it is a qualified path here, it should not contains legacy macros |
220 | self[module.local_id].scope.get(&segment) | 309 | module_data.scope.get(&segment) |
221 | } | 310 | } |
222 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | 311 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
223 | // enum variant | 312 | // enum variant |
@@ -319,7 +408,7 @@ impl CrateDefMap { | |||
319 | self | 408 | self |
320 | } else { | 409 | } else { |
321 | // Extend lifetime | 410 | // Extend lifetime |
322 | keep = db.crate_def_map(prelude.krate); | 411 | keep = prelude.def_map(db); |
323 | &keep | 412 | &keep |
324 | }; | 413 | }; |
325 | def_map[prelude.local_id].scope.get(name) | 414 | def_map[prelude.local_id].scope.get(name) |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index c459fa66d..bd3e2701b 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -11,17 +11,24 @@ use base_db::{fixture::WithFixture, SourceDatabase}; | |||
11 | use expect_test::{expect, Expect}; | 11 | use expect_test::{expect, Expect}; |
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 14 | use crate::{db::DefDatabase, test_db::TestDB}; |
15 | 15 | ||
16 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> { | 16 | use super::DefMap; |
17 | |||
18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | ||
17 | let db = TestDB::with_files(ra_fixture); | 19 | let db = TestDB::with_files(ra_fixture); |
18 | let krate = db.crate_graph().iter().next().unwrap(); | 20 | let krate = db.crate_graph().iter().next().unwrap(); |
19 | db.crate_def_map(krate) | 21 | db.crate_def_map(krate) |
20 | } | 22 | } |
21 | 23 | ||
24 | fn render_crate_def_map(ra_fixture: &str) -> String { | ||
25 | let db = TestDB::with_files(ra_fixture); | ||
26 | let krate = db.crate_graph().iter().next().unwrap(); | ||
27 | db.crate_def_map(krate).dump(&db) | ||
28 | } | ||
29 | |||
22 | fn check(ra_fixture: &str, expect: Expect) { | 30 | fn check(ra_fixture: &str, expect: Expect) { |
23 | let def_map = compute_crate_def_map(ra_fixture); | 31 | let actual = render_crate_def_map(ra_fixture); |
24 | let actual = def_map.dump(); | ||
25 | expect.assert_eq(&actual); | 32 | expect.assert_eq(&actual); |
26 | } | 33 | } |
27 | 34 | ||
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs index 58d69d3c6..e8e72e5ef 100644 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ b/crates/hir_def/src/nameres/tests/diagnostics.rs | |||
@@ -62,6 +62,22 @@ fn unresolved_extern_crate() { | |||
62 | } | 62 | } |
63 | 63 | ||
64 | #[test] | 64 | #[test] |
65 | fn extern_crate_self_as() { | ||
66 | mark::check!(extern_crate_self_as); | ||
67 | check_diagnostics( | ||
68 | r" | ||
69 | //- /lib.rs | ||
70 | extern crate doesnotexist; | ||
71 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ unresolved extern crate | ||
72 | // Should not error. | ||
73 | extern crate self as foo; | ||
74 | struct Foo; | ||
75 | use foo::Foo as Bar; | ||
76 | ", | ||
77 | ); | ||
78 | } | ||
79 | |||
80 | #[test] | ||
65 | fn dedup_unresolved_import_from_unresolved_crate() { | 81 | fn dedup_unresolved_import_from_unresolved_crate() { |
66 | check_diagnostics( | 82 | check_diagnostics( |
67 | r" | 83 | r" |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index e5e9e8ca1..36ed5e8ce 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -391,11 +391,21 @@ foo!(ok_shadow); | |||
391 | mod m4; | 391 | mod m4; |
392 | bar!(OkMacroUse); | 392 | bar!(OkMacroUse); |
393 | 393 | ||
394 | mod m5; | ||
395 | baz!(OkMacroUseInner); | ||
396 | |||
394 | //- /m3/m4.rs | 397 | //- /m3/m4.rs |
395 | foo!(ok_shadow_deep); | 398 | foo!(ok_shadow_deep); |
396 | macro_rules! bar { | 399 | macro_rules! bar { |
397 | ($x:ident) => { struct $x; } | 400 | ($x:ident) => { struct $x; } |
398 | } | 401 | } |
402 | //- /m3/m5.rs | ||
403 | #![macro_use] | ||
404 | macro_rules! baz { | ||
405 | ($x:ident) => { struct $x; } | ||
406 | } | ||
407 | |||
408 | |||
399 | "#, | 409 | "#, |
400 | expect![[r#" | 410 | expect![[r#" |
401 | crate | 411 | crate |
@@ -423,11 +433,15 @@ macro_rules! bar { | |||
423 | crate::m3 | 433 | crate::m3 |
424 | OkAfterInside: t v | 434 | OkAfterInside: t v |
425 | OkMacroUse: t v | 435 | OkMacroUse: t v |
436 | OkMacroUseInner: t v | ||
426 | m4: t | 437 | m4: t |
438 | m5: t | ||
427 | ok_shadow: v | 439 | ok_shadow: v |
428 | 440 | ||
429 | crate::m3::m4 | 441 | crate::m3::m4 |
430 | ok_shadow_deep: v | 442 | ok_shadow_deep: v |
443 | |||
444 | crate::m3::m5 | ||
431 | "#]], | 445 | "#]], |
432 | ); | 446 | ); |
433 | } | 447 | } |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e34cd7f2f..0e60dc2b6 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 20 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
21 | pub struct ModPath { | 21 | pub struct ModPath { |
22 | pub kind: PathKind, | 22 | pub kind: PathKind, |
23 | pub segments: Vec<Name>, | 23 | segments: Vec<Name>, |
24 | } | 24 | } |
25 | 25 | ||
26 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 26 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -53,6 +53,11 @@ impl ModPath { | |||
53 | ModPath { kind, segments } | 53 | ModPath { kind, segments } |
54 | } | 54 | } |
55 | 55 | ||
56 | /// Creates a `ModPath` from a `PathKind`, with no extra path segments. | ||
57 | pub const fn from_kind(kind: PathKind) -> ModPath { | ||
58 | ModPath { kind, segments: Vec::new() } | ||
59 | } | ||
60 | |||
56 | /// Calls `cb` with all paths, represented by this use item. | 61 | /// Calls `cb` with all paths, represented by this use item. |
57 | pub(crate) fn expand_use_item( | 62 | pub(crate) fn expand_use_item( |
58 | item_src: InFile<ast::Use>, | 63 | item_src: InFile<ast::Use>, |
@@ -64,6 +69,18 @@ impl ModPath { | |||
64 | } | 69 | } |
65 | } | 70 | } |
66 | 71 | ||
72 | pub fn segments(&self) -> &[Name] { | ||
73 | &self.segments | ||
74 | } | ||
75 | |||
76 | pub fn push_segment(&mut self, segment: Name) { | ||
77 | self.segments.push(segment); | ||
78 | } | ||
79 | |||
80 | pub fn pop_segment(&mut self) -> Option<Name> { | ||
81 | self.segments.pop() | ||
82 | } | ||
83 | |||
67 | /// Returns the number of segments in the path (counting special segments like `$crate` and | 84 | /// Returns the number of segments in the path (counting special segments like `$crate` and |
68 | /// `super`). | 85 | /// `super`). |
69 | pub fn len(&self) -> usize { | 86 | pub fn len(&self) -> usize { |
@@ -78,7 +95,7 @@ impl ModPath { | |||
78 | } | 95 | } |
79 | 96 | ||
80 | pub fn is_ident(&self) -> bool { | 97 | pub fn is_ident(&self) -> bool { |
81 | self.kind == PathKind::Plain && self.segments.len() == 1 | 98 | self.as_ident().is_some() |
82 | } | 99 | } |
83 | 100 | ||
84 | pub fn is_self(&self) -> bool { | 101 | pub fn is_self(&self) -> bool { |
@@ -87,10 +104,14 @@ impl ModPath { | |||
87 | 104 | ||
88 | /// If this path is a single identifier, like `foo`, return its name. | 105 | /// If this path is a single identifier, like `foo`, return its name. |
89 | pub fn as_ident(&self) -> Option<&Name> { | 106 | pub fn as_ident(&self) -> Option<&Name> { |
90 | if !self.is_ident() { | 107 | if self.kind != PathKind::Plain { |
91 | return None; | 108 | return None; |
92 | } | 109 | } |
93 | self.segments.first() | 110 | |
111 | match &*self.segments { | ||
112 | [name] => Some(name), | ||
113 | _ => None, | ||
114 | } | ||
94 | } | 115 | } |
95 | } | 116 | } |
96 | 117 | ||
@@ -180,10 +201,10 @@ impl Path { | |||
180 | } | 201 | } |
181 | let res = Path { | 202 | let res = Path { |
182 | type_anchor: self.type_anchor.clone(), | 203 | type_anchor: self.type_anchor.clone(), |
183 | mod_path: ModPath { | 204 | mod_path: ModPath::from_segments( |
184 | kind: self.mod_path.kind.clone(), | 205 | self.mod_path.kind.clone(), |
185 | segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), | 206 | self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(), |
186 | }, | 207 | ), |
187 | generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), | 208 | generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), |
188 | }; | 209 | }; |
189 | Some(res) | 210 | Some(res) |
@@ -304,6 +325,7 @@ pub use hir_expand::name as __name; | |||
304 | #[macro_export] | 325 | #[macro_export] |
305 | macro_rules! __known_path { | 326 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 327 | (core::iter::IntoIterator) => {}; |
328 | (core::iter::Iterator) => {}; | ||
307 | (core::result::Result) => {}; | 329 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | 330 | (core::option::Option) => {}; |
309 | (core::ops::Range) => {}; | 331 | (core::ops::Range) => {}; |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 9518ac109..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 |
@@ -129,7 +138,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
129 | } | 138 | } |
130 | } | 139 | } |
131 | 140 | ||
132 | let mod_path = ModPath { kind, segments }; | 141 | let mod_path = ModPath::from_segments(kind, segments); |
133 | return Some(Path { type_anchor, mod_path, generic_args }); | 142 | return Some(Path { type_anchor, mod_path, generic_args }); |
134 | 143 | ||
135 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { | 144 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { |
diff --git a/crates/hir_def/src/path/lower/lower_use.rs b/crates/hir_def/src/path/lower/lower_use.rs index ba0d1f0e7..d584b0b70 100644 --- a/crates/hir_def/src/path/lower/lower_use.rs +++ b/crates/hir_def/src/path/lower/lower_use.rs | |||
@@ -75,9 +75,10 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> | |||
75 | match hygiene.name_ref_to_name(name_ref) { | 75 | match hygiene.name_ref_to_name(name_ref) { |
76 | Either::Left(name) => { | 76 | Either::Left(name) => { |
77 | // no type args in use | 77 | // no type args in use |
78 | let mut res = prefix.unwrap_or_else(|| ModPath { | 78 | let mut res = prefix.unwrap_or_else(|| { |
79 | kind: segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), | 79 | ModPath::from_kind( |
80 | segments: Vec::with_capacity(1), | 80 | segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), |
81 | ) | ||
81 | }); | 82 | }); |
82 | res.segments.push(name); | 83 | res.segments.push(name); |
83 | res | 84 | res |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 85ddc2c47..e85f85e49 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -10,19 +10,19 @@ use rustc_hash::FxHashSet; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | body::scope::{ExprScopes, ScopeId}, | 12 | body::scope::{ExprScopes, ScopeId}, |
13 | body::Body, | ||
14 | builtin_type::BuiltinType, | 13 | builtin_type::BuiltinType, |
15 | db::DefDatabase, | 14 | db::DefDatabase, |
16 | expr::{ExprId, PatId}, | 15 | expr::{ExprId, PatId}, |
17 | generics::GenericParams, | 16 | generics::GenericParams, |
18 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, | 17 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, |
19 | nameres::CrateDefMap, | 18 | nameres::DefMap, |
20 | path::{ModPath, PathKind}, | 19 | path::{ModPath, PathKind}, |
21 | per_ns::PerNs, | 20 | per_ns::PerNs, |
22 | visibility::{RawVisibility, Visibility}, | 21 | visibility::{RawVisibility, Visibility}, |
23 | AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, | 22 | AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, |
24 | EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, | 23 | EnumVariantId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, |
25 | ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | 24 | LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, |
25 | TypeParamId, 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<CrateDefMap>, | 37 | crate_def_map: Arc<DefMap>, |
38 | module_id: LocalModuleId, | 38 | module_id: LocalModuleId, |
39 | } | 39 | } |
40 | 40 | ||
@@ -57,8 +57,6 @@ enum Scope { | |||
57 | AdtScope(AdtId), | 57 | AdtScope(AdtId), |
58 | /// Local bindings | 58 | /// Local bindings |
59 | ExprScope(ExprScope), | 59 | ExprScope(ExprScope), |
60 | /// Temporary hack to support local items. | ||
61 | LocalItemsScope(Arc<Body>), | ||
62 | } | 60 | } |
63 | 61 | ||
64 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 62 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -145,27 +143,34 @@ impl Resolver { | |||
145 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) | 143 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) |
146 | } | 144 | } |
147 | 145 | ||
146 | pub fn resolve_module_path_in_trait_items( | ||
147 | &self, | ||
148 | db: &dyn DefDatabase, | ||
149 | path: &ModPath, | ||
150 | ) -> Option<TraitId> { | ||
151 | let (item_map, module) = self.module_scope()?; | ||
152 | let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module); | ||
153 | match module_res.take_types()? { | ||
154 | ModuleDefId::TraitId(it) => Some(it), | ||
155 | _ => None, | ||
156 | } | ||
157 | } | ||
158 | |||
148 | pub fn resolve_path_in_type_ns( | 159 | pub fn resolve_path_in_type_ns( |
149 | &self, | 160 | &self, |
150 | db: &dyn DefDatabase, | 161 | db: &dyn DefDatabase, |
151 | path: &ModPath, | 162 | path: &ModPath, |
152 | ) -> Option<(TypeNs, Option<usize>)> { | 163 | ) -> Option<(TypeNs, Option<usize>)> { |
153 | let first_name = path.segments.first()?; | 164 | let first_name = path.segments().first()?; |
154 | let skip_to_mod = path.kind != PathKind::Plain; | 165 | let skip_to_mod = path.kind != PathKind::Plain; |
155 | for scope in self.scopes.iter().rev() { | 166 | for scope in self.scopes.iter().rev() { |
156 | match scope { | 167 | match scope { |
157 | Scope::ExprScope(_) => continue, | 168 | Scope::ExprScope(_) => continue, |
158 | Scope::GenericParams { .. } | 169 | Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue, |
159 | | Scope::ImplDefScope(_) | ||
160 | | Scope::LocalItemsScope(_) | ||
161 | if skip_to_mod => | ||
162 | { | ||
163 | continue | ||
164 | } | ||
165 | 170 | ||
166 | Scope::GenericParams { params, def } => { | 171 | Scope::GenericParams { params, def } => { |
167 | if let Some(local_id) = params.find_type_by_name(first_name) { | 172 | if let Some(local_id) = params.find_type_by_name(first_name) { |
168 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 173 | let idx = if path.segments().len() == 1 { None } else { Some(1) }; |
169 | return Some(( | 174 | return Some(( |
170 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), | 175 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), |
171 | idx, | 176 | idx, |
@@ -174,52 +179,24 @@ impl Resolver { | |||
174 | } | 179 | } |
175 | Scope::ImplDefScope(impl_) => { | 180 | Scope::ImplDefScope(impl_) => { |
176 | if first_name == &name![Self] { | 181 | if first_name == &name![Self] { |
177 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 182 | let idx = if path.segments().len() == 1 { None } else { Some(1) }; |
178 | return Some((TypeNs::SelfType(*impl_), idx)); | 183 | return Some((TypeNs::SelfType(*impl_), idx)); |
179 | } | 184 | } |
180 | } | 185 | } |
181 | Scope::AdtScope(adt) => { | 186 | Scope::AdtScope(adt) => { |
182 | if first_name == &name![Self] { | 187 | if first_name == &name![Self] { |
183 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 188 | let idx = if path.segments().len() == 1 { None } else { Some(1) }; |
184 | return Some((TypeNs::AdtSelfType(*adt), idx)); | 189 | return Some((TypeNs::AdtSelfType(*adt), idx)); |
185 | } | 190 | } |
186 | } | 191 | } |
187 | Scope::ModuleScope(m) => { | 192 | Scope::ModuleScope(m) => { |
188 | let (module_def, idx) = m.crate_def_map.resolve_path( | 193 | if let Some(res) = m.resolve_path_in_type_ns(db, path) { |
189 | db, | 194 | return Some(res); |
190 | m.module_id, | ||
191 | &path, | ||
192 | BuiltinShadowMode::Other, | ||
193 | ); | ||
194 | let res = to_type_ns(module_def)?; | ||
195 | return Some((res, idx)); | ||
196 | } | ||
197 | Scope::LocalItemsScope(body) => { | ||
198 | let def = body.item_scope.get(first_name); | ||
199 | if let Some(res) = to_type_ns(def) { | ||
200 | return Some((res, None)); | ||
201 | } | 195 | } |
202 | } | 196 | } |
203 | } | 197 | } |
204 | } | 198 | } |
205 | return None; | 199 | None |
206 | fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> { | ||
207 | let res = match per_ns.take_types()? { | ||
208 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
209 | ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), | ||
210 | |||
211 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
212 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
213 | |||
214 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
215 | |||
216 | ModuleDefId::FunctionId(_) | ||
217 | | ModuleDefId::ConstId(_) | ||
218 | | ModuleDefId::StaticId(_) | ||
219 | | ModuleDefId::ModuleId(_) => return None, | ||
220 | }; | ||
221 | Some(res) | ||
222 | } | ||
223 | } | 200 | } |
224 | 201 | ||
225 | pub fn resolve_path_in_type_ns_fully( | 202 | pub fn resolve_path_in_type_ns_fully( |
@@ -256,9 +233,9 @@ impl Resolver { | |||
256 | db: &dyn DefDatabase, | 233 | db: &dyn DefDatabase, |
257 | path: &ModPath, | 234 | path: &ModPath, |
258 | ) -> Option<ResolveValueResult> { | 235 | ) -> Option<ResolveValueResult> { |
259 | let n_segments = path.segments.len(); | 236 | let n_segments = path.segments().len(); |
260 | let tmp = name![self]; | 237 | let tmp = name![self]; |
261 | let first_name = if path.is_self() { &tmp } else { path.segments.first()? }; | 238 | let first_name = if path.is_self() { &tmp } else { path.segments().first()? }; |
262 | let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); | 239 | let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); |
263 | for scope in self.scopes.iter().rev() { | 240 | for scope in self.scopes.iter().rev() { |
264 | match scope { | 241 | match scope { |
@@ -266,7 +243,6 @@ impl Resolver { | |||
266 | | Scope::ExprScope(_) | 243 | | Scope::ExprScope(_) |
267 | | Scope::GenericParams { .. } | 244 | | Scope::GenericParams { .. } |
268 | | Scope::ImplDefScope(_) | 245 | | Scope::ImplDefScope(_) |
269 | | Scope::LocalItemsScope(_) | ||
270 | if skip_to_mod => | 246 | if skip_to_mod => |
271 | { | 247 | { |
272 | continue | 248 | continue |
@@ -321,63 +297,14 @@ impl Resolver { | |||
321 | } | 297 | } |
322 | 298 | ||
323 | Scope::ModuleScope(m) => { | 299 | Scope::ModuleScope(m) => { |
324 | let (module_def, idx) = m.crate_def_map.resolve_path( | 300 | if let Some(def) = m.resolve_path_in_value_ns(db, path) { |
325 | db, | 301 | return Some(def); |
326 | m.module_id, | ||
327 | &path, | ||
328 | BuiltinShadowMode::Other, | ||
329 | ); | ||
330 | return match idx { | ||
331 | None => { | ||
332 | let value = to_value_ns(module_def)?; | ||
333 | Some(ResolveValueResult::ValueNs(value)) | ||
334 | } | ||
335 | Some(idx) => { | ||
336 | let ty = match module_def.take_types()? { | ||
337 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
338 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
339 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
340 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
341 | |||
342 | ModuleDefId::ModuleId(_) | ||
343 | | ModuleDefId::FunctionId(_) | ||
344 | | ModuleDefId::EnumVariantId(_) | ||
345 | | ModuleDefId::ConstId(_) | ||
346 | | ModuleDefId::StaticId(_) => return None, | ||
347 | }; | ||
348 | Some(ResolveValueResult::Partial(ty, idx)) | ||
349 | } | ||
350 | }; | ||
351 | } | ||
352 | Scope::LocalItemsScope(body) => { | ||
353 | // we don't bother looking in the builtin scope here because there are no builtin values | ||
354 | let def = to_value_ns(body.item_scope.get(first_name)); | ||
355 | |||
356 | if let Some(res) = def { | ||
357 | return Some(ResolveValueResult::ValueNs(res)); | ||
358 | } | 302 | } |
359 | } | 303 | } |
360 | } | 304 | } |
361 | } | 305 | } |
362 | return None; | 306 | |
363 | 307 | None | |
364 | fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { | ||
365 | let res = match per_ns.take_values()? { | ||
366 | ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), | ||
367 | ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), | ||
368 | ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), | ||
369 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | ||
370 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | ||
371 | |||
372 | ModuleDefId::AdtId(AdtId::EnumId(_)) | ||
373 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
374 | | ModuleDefId::TraitId(_) | ||
375 | | ModuleDefId::TypeAliasId(_) | ||
376 | | ModuleDefId::BuiltinType(_) | ||
377 | | ModuleDefId::ModuleId(_) => return None, | ||
378 | }; | ||
379 | Some(res) | ||
380 | } | ||
381 | } | 308 | } |
382 | 309 | ||
383 | pub fn resolve_path_in_value_ns_fully( | 310 | pub fn resolve_path_in_value_ns_fully( |
@@ -396,11 +323,6 @@ impl Resolver { | |||
396 | db: &dyn DefDatabase, | 323 | db: &dyn DefDatabase, |
397 | path: &ModPath, | 324 | path: &ModPath, |
398 | ) -> Option<MacroDefId> { | 325 | ) -> Option<MacroDefId> { |
399 | // Search item scope legacy macro first | ||
400 | if let Some(def) = self.resolve_local_macro_def(path) { | ||
401 | return Some(def); | ||
402 | } | ||
403 | |||
404 | let (item_map, module) = self.module_scope()?; | 326 | let (item_map, module) = self.module_scope()?; |
405 | item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() | 327 | item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() |
406 | } | 328 | } |
@@ -415,8 +337,8 @@ impl Resolver { | |||
415 | let mut traits = FxHashSet::default(); | 337 | let mut traits = FxHashSet::default(); |
416 | for scope in &self.scopes { | 338 | for scope in &self.scopes { |
417 | if let Scope::ModuleScope(m) = scope { | 339 | if let Scope::ModuleScope(m) = scope { |
418 | if let Some(prelude) = m.crate_def_map.prelude { | 340 | if let Some(prelude) = m.crate_def_map.prelude() { |
419 | let prelude_def_map = db.crate_def_map(prelude.krate); | 341 | let prelude_def_map = prelude.def_map(db); |
420 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 342 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
421 | } | 343 | } |
422 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); | 344 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); |
@@ -425,7 +347,7 @@ impl Resolver { | |||
425 | traits | 347 | traits |
426 | } | 348 | } |
427 | 349 | ||
428 | fn module_scope(&self) -> Option<(&CrateDefMap, LocalModuleId)> { | 350 | fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> { |
429 | self.scopes.iter().rev().find_map(|scope| match scope { | 351 | self.scopes.iter().rev().find_map(|scope| match scope { |
430 | Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), | 352 | Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), |
431 | 353 | ||
@@ -433,23 +355,14 @@ impl Resolver { | |||
433 | }) | 355 | }) |
434 | } | 356 | } |
435 | 357 | ||
436 | fn resolve_local_macro_def(&self, path: &ModPath) -> Option<MacroDefId> { | ||
437 | let name = path.as_ident()?; | ||
438 | self.scopes.iter().rev().find_map(|scope| { | ||
439 | if let Scope::LocalItemsScope(body) = scope { | ||
440 | return body.item_scope.get_legacy_macro(name); | ||
441 | } | ||
442 | None | ||
443 | }) | ||
444 | } | ||
445 | |||
446 | pub fn module(&self) -> Option<ModuleId> { | 358 | pub fn module(&self) -> Option<ModuleId> { |
447 | let (def_map, local_id) = self.module_scope()?; | 359 | let (def_map, local_id) = self.module_scope()?; |
448 | Some(ModuleId { krate: def_map.krate, local_id }) | 360 | Some(def_map.module_id(local_id)) |
449 | } | 361 | } |
450 | 362 | ||
451 | pub fn krate(&self) -> Option<CrateId> { | 363 | pub fn krate(&self) -> Option<CrateId> { |
452 | self.module_scope().map(|t| t.0.krate) | 364 | // FIXME: can this ever be `None`? |
365 | self.module_scope().map(|t| t.0.krate()) | ||
453 | } | 366 | } |
454 | 367 | ||
455 | pub fn where_predicates_in_scope<'a>( | 368 | pub fn where_predicates_in_scope<'a>( |
@@ -484,7 +397,7 @@ pub enum ScopeDef { | |||
484 | PerNs(PerNs), | 397 | PerNs(PerNs), |
485 | ImplSelfType(ImplId), | 398 | ImplSelfType(ImplId), |
486 | AdtSelfType(AdtId), | 399 | AdtSelfType(AdtId), |
487 | GenericParam(TypeParamId), | 400 | GenericParam(GenericParamId), |
488 | Local(PatId), | 401 | Local(PatId), |
489 | } | 402 | } |
490 | 403 | ||
@@ -508,14 +421,14 @@ impl Scope { | |||
508 | seen.insert((name.clone(), scope)); | 421 | seen.insert((name.clone(), scope)); |
509 | f(name.clone(), ScopeDef::PerNs(scope)); | 422 | f(name.clone(), ScopeDef::PerNs(scope)); |
510 | }); | 423 | }); |
511 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | 424 | m.crate_def_map.extern_prelude().for_each(|(name, &def)| { |
512 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); | 425 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); |
513 | }); | 426 | }); |
514 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { | 427 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { |
515 | f(name.clone(), ScopeDef::PerNs(def)); | 428 | f(name.clone(), ScopeDef::PerNs(def)); |
516 | }); | 429 | }); |
517 | if let Some(prelude) = m.crate_def_map.prelude { | 430 | if let Some(prelude) = m.crate_def_map.prelude() { |
518 | let prelude_def_map = db.crate_def_map(prelude.krate); | 431 | let prelude_def_map = prelude.def_map(db); |
519 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { | 432 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { |
520 | let seen_tuple = (name.clone(), def); | 433 | let seen_tuple = (name.clone(), def); |
521 | if !seen.contains(&seen_tuple) { | 434 | if !seen.contains(&seen_tuple) { |
@@ -524,18 +437,21 @@ impl Scope { | |||
524 | }); | 437 | }); |
525 | } | 438 | } |
526 | } | 439 | } |
527 | Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| { | 440 | &Scope::GenericParams { ref params, def: parent } => { |
528 | f(name.clone(), ScopeDef::PerNs(def)); | ||
529 | }), | ||
530 | Scope::GenericParams { params, def } => { | ||
531 | for (local_id, param) in params.types.iter() { | 441 | for (local_id, param) in params.types.iter() { |
532 | if let Some(name) = ¶m.name { | 442 | if let Some(ref name) = param.name { |
533 | f( | 443 | let id = TypeParamId { local_id, parent }; |
534 | name.clone(), | 444 | f(name.clone(), ScopeDef::GenericParam(id.into())) |
535 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), | ||
536 | ) | ||
537 | } | 445 | } |
538 | } | 446 | } |
447 | for (local_id, param) in params.consts.iter() { | ||
448 | let id = ConstParamId { local_id, parent }; | ||
449 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) | ||
450 | } | ||
451 | for (local_id, param) in params.lifetimes.iter() { | ||
452 | let id = LifetimeParamId { local_id, parent }; | ||
453 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) | ||
454 | } | ||
539 | } | 455 | } |
540 | Scope::ImplDefScope(i) => { | 456 | Scope::ImplDefScope(i) => { |
541 | f(name![Self], ScopeDef::ImplSelfType(*i)); | 457 | f(name![Self], ScopeDef::ImplSelfType(*i)); |
@@ -564,10 +480,19 @@ pub fn resolver_for_scope( | |||
564 | scope_id: Option<ScopeId>, | 480 | scope_id: Option<ScopeId>, |
565 | ) -> Resolver { | 481 | ) -> Resolver { |
566 | let mut r = owner.resolver(db); | 482 | let mut r = owner.resolver(db); |
567 | r = r.push_local_items_scope(db.body(owner)); | ||
568 | let scopes = db.expr_scopes(owner); | 483 | let scopes = db.expr_scopes(owner); |
569 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); | 484 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); |
570 | for scope in scope_chain.into_iter().rev() { | 485 | for scope in scope_chain.into_iter().rev() { |
486 | if let Some(block) = scopes.block(scope) { | ||
487 | if let Some(def_map) = db.block_def_map(block) { | ||
488 | let root = def_map.root(); | ||
489 | r = r.push_module_scope(def_map, root); | ||
490 | // FIXME: This adds as many module scopes as there are blocks, but resolving in each | ||
491 | // already traverses all parents, so this is O(n²). I think we could only store the | ||
492 | // innermost module scope instead? | ||
493 | } | ||
494 | } | ||
495 | |||
571 | r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); | 496 | r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); |
572 | } | 497 | } |
573 | r | 498 | r |
@@ -588,18 +513,10 @@ impl Resolver { | |||
588 | self.push_scope(Scope::ImplDefScope(impl_def)) | 513 | self.push_scope(Scope::ImplDefScope(impl_def)) |
589 | } | 514 | } |
590 | 515 | ||
591 | fn push_module_scope( | 516 | fn push_module_scope(self, crate_def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver { |
592 | self, | ||
593 | crate_def_map: Arc<CrateDefMap>, | ||
594 | module_id: LocalModuleId, | ||
595 | ) -> Resolver { | ||
596 | self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) | 517 | self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) |
597 | } | 518 | } |
598 | 519 | ||
599 | fn push_local_items_scope(self, body: Arc<Body>) -> Resolver { | ||
600 | self.push_scope(Scope::LocalItemsScope(body)) | ||
601 | } | ||
602 | |||
603 | fn push_expr_scope( | 520 | fn push_expr_scope( |
604 | self, | 521 | self, |
605 | owner: DefWithBodyId, | 522 | owner: DefWithBodyId, |
@@ -610,6 +527,85 @@ impl Resolver { | |||
610 | } | 527 | } |
611 | } | 528 | } |
612 | 529 | ||
530 | impl ModuleItemMap { | ||
531 | fn resolve_path_in_value_ns( | ||
532 | &self, | ||
533 | db: &dyn DefDatabase, | ||
534 | path: &ModPath, | ||
535 | ) -> Option<ResolveValueResult> { | ||
536 | let (module_def, idx) = | ||
537 | self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | ||
538 | match idx { | ||
539 | None => { | ||
540 | let value = to_value_ns(module_def)?; | ||
541 | Some(ResolveValueResult::ValueNs(value)) | ||
542 | } | ||
543 | Some(idx) => { | ||
544 | let ty = match module_def.take_types()? { | ||
545 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
546 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
547 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
548 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
549 | |||
550 | ModuleDefId::ModuleId(_) | ||
551 | | ModuleDefId::FunctionId(_) | ||
552 | | ModuleDefId::EnumVariantId(_) | ||
553 | | ModuleDefId::ConstId(_) | ||
554 | | ModuleDefId::StaticId(_) => return None, | ||
555 | }; | ||
556 | Some(ResolveValueResult::Partial(ty, idx)) | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | |||
561 | fn resolve_path_in_type_ns( | ||
562 | &self, | ||
563 | db: &dyn DefDatabase, | ||
564 | path: &ModPath, | ||
565 | ) -> Option<(TypeNs, Option<usize>)> { | ||
566 | let (module_def, idx) = | ||
567 | self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | ||
568 | let res = to_type_ns(module_def)?; | ||
569 | Some((res, idx)) | ||
570 | } | ||
571 | } | ||
572 | |||
573 | fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { | ||
574 | let res = match per_ns.take_values()? { | ||
575 | ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), | ||
576 | ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), | ||
577 | ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), | ||
578 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | ||
579 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | ||
580 | |||
581 | ModuleDefId::AdtId(AdtId::EnumId(_)) | ||
582 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
583 | | ModuleDefId::TraitId(_) | ||
584 | | ModuleDefId::TypeAliasId(_) | ||
585 | | ModuleDefId::BuiltinType(_) | ||
586 | | ModuleDefId::ModuleId(_) => return None, | ||
587 | }; | ||
588 | Some(res) | ||
589 | } | ||
590 | |||
591 | fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> { | ||
592 | let res = match per_ns.take_types()? { | ||
593 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
594 | ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), | ||
595 | |||
596 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
597 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
598 | |||
599 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
600 | |||
601 | ModuleDefId::FunctionId(_) | ||
602 | | ModuleDefId::ConstId(_) | ||
603 | | ModuleDefId::StaticId(_) | ||
604 | | ModuleDefId::ModuleId(_) => return None, | ||
605 | }; | ||
606 | Some(res) | ||
607 | } | ||
608 | |||
613 | pub trait HasResolver: Copy { | 609 | pub trait HasResolver: Copy { |
614 | /// Builds a resolver for type references inside this def. | 610 | /// Builds a resolver for type references inside this def. |
615 | fn resolver(self, db: &dyn DefDatabase) -> Resolver; | 611 | fn resolver(self, db: &dyn DefDatabase) -> Resolver; |
@@ -617,7 +613,7 @@ pub trait HasResolver: Copy { | |||
617 | 613 | ||
618 | impl HasResolver for ModuleId { | 614 | impl HasResolver for ModuleId { |
619 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 615 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
620 | let def_map = db.crate_def_map(self.krate); | 616 | let def_map = self.def_map(db); |
621 | Resolver::default().push_module_scope(def_map, self.local_id) | 617 | Resolver::default().push_module_scope(def_map, self.local_id) |
622 | } | 618 | } |
623 | } | 619 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index 574c0201a..eda982c85 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -5,17 +5,17 @@ use std::{ | |||
5 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast}; | 8 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition, Upcast}; |
9 | use base_db::{AnchoredPath, SourceDatabase}; | 9 | use base_db::{AnchoredPath, SourceDatabase}; |
10 | use hir_expand::db::AstDatabase; | ||
11 | use hir_expand::diagnostics::Diagnostic; | 10 | use hir_expand::diagnostics::Diagnostic; |
12 | use hir_expand::diagnostics::DiagnosticSinkBuilder; | 11 | use hir_expand::diagnostics::DiagnosticSinkBuilder; |
12 | use hir_expand::{db::AstDatabase, InFile}; | ||
13 | use rustc_hash::FxHashMap; | 13 | use rustc_hash::FxHashMap; |
14 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
15 | use syntax::{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, ModuleDefId}; | 18 | use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; |
19 | 19 | ||
20 | #[salsa::database( | 20 | #[salsa::database( |
21 | base_db::SourceDatabaseExtStorage, | 21 | base_db::SourceDatabaseExtStorage, |
@@ -72,18 +72,109 @@ impl FileLoader for TestDB { | |||
72 | } | 72 | } |
73 | 73 | ||
74 | impl TestDB { | 74 | impl TestDB { |
75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { | 75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { |
76 | for &krate in self.relevant_crates(file_id).iter() { | 76 | for &krate in self.relevant_crates(file_id).iter() { |
77 | let crate_def_map = self.crate_def_map(krate); | 77 | let crate_def_map = self.crate_def_map(krate); |
78 | for (local_id, data) in crate_def_map.modules.iter() { | 78 | for (local_id, data) in crate_def_map.modules() { |
79 | if data.origin.file_id() == Some(file_id) { | 79 | if data.origin.file_id() == Some(file_id) { |
80 | return crate::ModuleId { krate, local_id }; | 80 | return crate_def_map.module_id(local_id); |
81 | } | 81 | } |
82 | } | 82 | } |
83 | } | 83 | } |
84 | panic!("Can't find module for file") | 84 | panic!("Can't find module for file") |
85 | } | 85 | } |
86 | 86 | ||
87 | pub(crate) fn module_at_position(&self, position: FilePosition) -> ModuleId { | ||
88 | let file_module = self.module_for_file(position.file_id); | ||
89 | let mut def_map = file_module.def_map(self); | ||
90 | |||
91 | def_map = match self.block_at_position(&def_map, position) { | ||
92 | Some(it) => it, | ||
93 | None => return file_module, | ||
94 | }; | ||
95 | loop { | ||
96 | let new_map = self.block_at_position(&def_map, position); | ||
97 | match new_map { | ||
98 | Some(new_block) if !Arc::ptr_eq(&new_block, &def_map) => { | ||
99 | def_map = new_block; | ||
100 | } | ||
101 | _ => { | ||
102 | // FIXME: handle `mod` inside block expression | ||
103 | return def_map.module_id(def_map.root()); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option<Arc<DefMap>> { | ||
110 | // Find the smallest (innermost) function in `def_map` containing the cursor. | ||
111 | let mut size = None; | ||
112 | let mut fn_def = None; | ||
113 | for (_, module) in def_map.modules() { | ||
114 | let file_id = module.definition_source(self).file_id; | ||
115 | if file_id != position.file_id.into() { | ||
116 | continue; | ||
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() { | ||
122 | if let ModuleDefId::FunctionId(it) = decl { | ||
123 | let ast = | ||
124 | ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root); | ||
125 | let range = ast.syntax().text_range(); | ||
126 | |||
127 | if !range.contains(position.offset) { | ||
128 | continue; | ||
129 | } | ||
130 | |||
131 | let new_size = match size { | ||
132 | None => range.len(), | ||
133 | Some(size) => { | ||
134 | if range.len() < size { | ||
135 | range.len() | ||
136 | } else { | ||
137 | size | ||
138 | } | ||
139 | } | ||
140 | }; | ||
141 | if size != Some(new_size) { | ||
142 | size = Some(new_size); | ||
143 | fn_def = Some(it); | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | // Find the innermost block expression that has a `DefMap`. | ||
150 | let def_with_body = fn_def?.into(); | ||
151 | let (_, source_map) = self.body_with_source_map(def_with_body); | ||
152 | let scopes = self.expr_scopes(def_with_body); | ||
153 | let root = self.parse(position.file_id); | ||
154 | |||
155 | let scope_iter = algo::ancestors_at_offset(&root.syntax_node(), position.offset) | ||
156 | .filter_map(|node| { | ||
157 | let block = ast::BlockExpr::cast(node)?; | ||
158 | let expr = ast::Expr::from(block); | ||
159 | let expr_id = source_map.node_expr(InFile::new(position.file_id.into(), &expr))?; | ||
160 | let scope = scopes.scope_for(expr_id).unwrap(); | ||
161 | Some(scope) | ||
162 | }); | ||
163 | |||
164 | for scope in scope_iter { | ||
165 | let containing_blocks = | ||
166 | scopes.scope_chain(Some(scope)).filter_map(|scope| scopes.block(scope)); | ||
167 | |||
168 | for block in containing_blocks { | ||
169 | if let Some(def_map) = self.block_def_map(block) { | ||
170 | return Some(def_map); | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
175 | None | ||
176 | } | ||
177 | |||
87 | pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> { | 178 | pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> { |
88 | *self.events.lock().unwrap() = Some(Vec::new()); | 179 | *self.events.lock().unwrap() = Some(Vec::new()); |
89 | f(); | 180 | f(); |
@@ -110,7 +201,7 @@ impl TestDB { | |||
110 | let crate_graph = self.crate_graph(); | 201 | let crate_graph = self.crate_graph(); |
111 | for krate in crate_graph.iter() { | 202 | for krate in crate_graph.iter() { |
112 | let crate_def_map = self.crate_def_map(krate); | 203 | let crate_def_map = self.crate_def_map(krate); |
113 | for (module_id, _) in crate_def_map.modules.iter() { | 204 | for (module_id, _) in crate_def_map.modules() { |
114 | let file_id = crate_def_map[module_id].origin.file_id(); | 205 | let file_id = crate_def_map[module_id].origin.file_id(); |
115 | files.extend(file_id) | 206 | files.extend(file_id) |
116 | } | 207 | } |
@@ -135,7 +226,7 @@ impl TestDB { | |||
135 | let crate_def_map = self.crate_def_map(krate); | 226 | let crate_def_map = self.crate_def_map(krate); |
136 | 227 | ||
137 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 228 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
138 | for (module_id, module) in crate_def_map.modules.iter() { | 229 | for (module_id, module) in crate_def_map.modules() { |
139 | crate_def_map.add_diagnostics(self, module_id, &mut sink); | 230 | crate_def_map.add_diagnostics(self, module_id, &mut sink); |
140 | 231 | ||
141 | for decl in module.scope.declarations() { | 232 | for decl in module.scope.declarations() { |
@@ -161,7 +252,7 @@ impl TestDB { | |||
161 | let node = src.map(|ptr| ptr.to_node(&root)); | 252 | let node = src.map(|ptr| ptr.to_node(&root)); |
162 | let frange = node.as_ref().original_file_range(db); | 253 | let frange = node.as_ref().original_file_range(db); |
163 | 254 | ||
164 | let message = d.message().to_owned(); | 255 | let message = d.message(); |
165 | actual.entry(frange.file_id).or_default().push((frange.range, message)); | 256 | actual.entry(frange.file_id).or_default().push((frange.range, message)); |
166 | }); | 257 | }); |
167 | 258 | ||
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index f3bc9d680..0e3951910 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -5,7 +5,7 @@ use syntax::ast; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | nameres::CrateDefMap, | 8 | nameres::DefMap, |
9 | path::{ModPath, PathKind}, | 9 | path::{ModPath, PathKind}, |
10 | ModuleId, | 10 | ModuleId, |
11 | }; | 11 | }; |
@@ -22,8 +22,7 @@ pub enum RawVisibility { | |||
22 | 22 | ||
23 | impl RawVisibility { | 23 | impl RawVisibility { |
24 | pub(crate) const fn private() -> RawVisibility { | 24 | pub(crate) const fn private() -> RawVisibility { |
25 | let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() }; | 25 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) |
26 | RawVisibility::Module(path) | ||
27 | } | 26 | } |
28 | 27 | ||
29 | pub(crate) fn from_ast( | 28 | pub(crate) fn from_ast( |
@@ -59,15 +58,15 @@ impl RawVisibility { | |||
59 | RawVisibility::Module(path) | 58 | RawVisibility::Module(path) |
60 | } | 59 | } |
61 | ast::VisibilityKind::PubCrate => { | 60 | ast::VisibilityKind::PubCrate => { |
62 | let path = ModPath { kind: PathKind::Crate, segments: Vec::new() }; | 61 | let path = ModPath::from_kind(PathKind::Crate); |
63 | RawVisibility::Module(path) | 62 | RawVisibility::Module(path) |
64 | } | 63 | } |
65 | ast::VisibilityKind::PubSuper => { | 64 | ast::VisibilityKind::PubSuper => { |
66 | let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; | 65 | let path = ModPath::from_kind(PathKind::Super(1)); |
67 | RawVisibility::Module(path) | 66 | RawVisibility::Module(path) |
68 | } | 67 | } |
69 | ast::VisibilityKind::PubSelf => { | 68 | ast::VisibilityKind::PubSelf => { |
70 | let path = ModPath { kind: PathKind::Plain, segments: Vec::new() }; | 69 | let path = ModPath::from_kind(PathKind::Plain); |
71 | RawVisibility::Module(path) | 70 | RawVisibility::Module(path) |
72 | } | 71 | } |
73 | ast::VisibilityKind::Pub => RawVisibility::Public, | 72 | ast::VisibilityKind::Pub => RawVisibility::Public, |
@@ -103,8 +102,8 @@ impl Visibility { | |||
103 | if from_module.krate != to_module.krate { | 102 | if from_module.krate != to_module.krate { |
104 | return false; | 103 | return false; |
105 | } | 104 | } |
106 | let def_map = db.crate_def_map(from_module.krate); | 105 | let def_map = from_module.def_map(db); |
107 | self.is_visible_from_def_map(&def_map, from_module.local_id) | 106 | self.is_visible_from_def_map(db, &def_map, from_module.local_id) |
108 | } | 107 | } |
109 | 108 | ||
110 | pub(crate) fn is_visible_from_other_crate(self) -> bool { | 109 | pub(crate) fn is_visible_from_other_crate(self) -> bool { |
@@ -116,26 +115,48 @@ impl Visibility { | |||
116 | 115 | ||
117 | pub(crate) fn is_visible_from_def_map( | 116 | pub(crate) fn is_visible_from_def_map( |
118 | self, | 117 | self, |
119 | def_map: &CrateDefMap, | 118 | db: &dyn DefDatabase, |
120 | from_module: crate::LocalModuleId, | 119 | def_map: &DefMap, |
120 | mut from_module: crate::LocalModuleId, | ||
121 | ) -> bool { | 121 | ) -> bool { |
122 | let to_module = match self { | 122 | let to_module = match self { |
123 | Visibility::Module(m) => m, | 123 | Visibility::Module(m) => m, |
124 | Visibility::Public => return true, | 124 | Visibility::Public => return true, |
125 | }; | 125 | }; |
126 | |||
126 | // from_module needs to be a descendant of to_module | 127 | // from_module needs to be a descendant of to_module |
127 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | 128 | let mut def_map = def_map; |
128 | let parent_id = def_map[*m].parent?; | 129 | let mut parent_arc; |
129 | Some(parent_id) | 130 | loop { |
130 | }); | 131 | if def_map.module_id(from_module) == to_module { |
131 | ancestors.any(|m| m == to_module.local_id) | 132 | return true; |
133 | } | ||
134 | match def_map[from_module].parent { | ||
135 | Some(parent) => { | ||
136 | from_module = parent; | ||
137 | } | ||
138 | None => { | ||
139 | match def_map.parent() { | ||
140 | Some(module) => { | ||
141 | parent_arc = module.def_map(db); | ||
142 | def_map = &*parent_arc; | ||
143 | from_module = module.local_id; | ||
144 | } | ||
145 | None => { | ||
146 | // Reached the root module, nothing left to check. | ||
147 | return false; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | } | ||
132 | } | 153 | } |
133 | 154 | ||
134 | /// Returns the most permissive visibility of `self` and `other`. | 155 | /// Returns the most permissive visibility of `self` and `other`. |
135 | /// | 156 | /// |
136 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only | 157 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only |
137 | /// visible in unrelated modules). | 158 | /// visible in unrelated modules). |
138 | pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { | 159 | pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> { |
139 | match (self, other) { | 160 | match (self, other) { |
140 | (Visibility::Module(_), Visibility::Public) | 161 | (Visibility::Module(_), Visibility::Public) |
141 | | (Visibility::Public, Visibility::Module(_)) | 162 | | (Visibility::Public, Visibility::Module(_)) |