aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/attr.rs2
-rw-r--r--crates/hir_def/src/body/scope.rs57
-rw-r--r--crates/hir_def/src/find_path.rs56
-rw-r--r--crates/hir_def/src/nameres.rs17
-rw-r--r--crates/hir_def/src/nameres/collector.rs178
-rw-r--r--crates/hir_def/src/nameres/mod_resolution.rs13
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs2
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs21
-rw-r--r--crates/hir_def/src/resolver.rs24
9 files changed, 250 insertions, 120 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 2c10f46d8..52a2bce9b 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -638,7 +638,7 @@ fn collect_attrs(
638 owner: &dyn ast::AttrsOwner, 638 owner: &dyn ast::AttrsOwner,
639) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { 639) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> {
640 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) 640 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
641 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); 641 .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs)));
642 642
643 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); 643 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
644 let attrs = outer_attrs 644 let attrs = outer_attrs
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs
index 1bbb54fc6..bd7005ca6 100644
--- a/crates/hir_def/src/body/scope.rs
+++ b/crates/hir_def/src/body/scope.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8use crate::{ 8use crate::{
9 body::Body, 9 body::Body,
10 db::DefDatabase, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, LabelId, Pat, PatId, Statement},
12 BlockId, DefWithBodyId, 12 BlockId, DefWithBodyId,
13}; 13};
14 14
@@ -40,6 +40,7 @@ impl ScopeEntry {
40pub struct ScopeData { 40pub struct ScopeData {
41 parent: Option<ScopeId>, 41 parent: Option<ScopeId>,
42 block: Option<BlockId>, 42 block: Option<BlockId>,
43 label: Option<(LabelId, Name)>,
43 entries: Vec<ScopeEntry>, 44 entries: Vec<ScopeEntry>,
44} 45}
45 46
@@ -67,6 +68,11 @@ impl ExprScopes {
67 self.scopes[scope].block 68 self.scopes[scope].block
68 } 69 }
69 70
71 /// If `scope` refers to a labeled expression scope, returns the corresponding `Label`.
72 pub fn label(&self, scope: ScopeId) -> Option<(LabelId, Name)> {
73 self.scopes[scope].label.clone()
74 }
75
70 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { 76 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ {
71 std::iter::successors(scope, move |&scope| self.scopes[scope].parent) 77 std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
72 } 78 }
@@ -85,15 +91,34 @@ impl ExprScopes {
85 } 91 }
86 92
87 fn root_scope(&mut self) -> ScopeId { 93 fn root_scope(&mut self) -> ScopeId {
88 self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] }) 94 self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] })
89 } 95 }
90 96
91 fn new_scope(&mut self, parent: ScopeId) -> ScopeId { 97 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
92 self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] }) 98 self.scopes.alloc(ScopeData {
99 parent: Some(parent),
100 block: None,
101 label: None,
102 entries: vec![],
103 })
93 } 104 }
94 105
95 fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId { 106 fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId {
96 self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] }) 107 self.scopes.alloc(ScopeData { parent: Some(parent), block: None, label, entries: vec![] })
108 }
109
110 fn new_block_scope(
111 &mut self,
112 parent: ScopeId,
113 block: BlockId,
114 label: Option<(LabelId, Name)>,
115 ) -> ScopeId {
116 self.scopes.alloc(ScopeData {
117 parent: Some(parent),
118 block: Some(block),
119 label,
120 entries: vec![],
121 })
97 } 122 }
98 123
99 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 124 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
@@ -144,21 +169,33 @@ fn compute_block_scopes(
144} 169}
145 170
146fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 171fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
172 let make_label =
173 |label: &Option<_>| label.map(|label| (label, body.labels[label].name.clone()));
174
147 scopes.set_scope(expr, scope); 175 scopes.set_scope(expr, scope);
148 match &body[expr] { 176 match &body[expr] {
149 Expr::Block { statements, tail, id, .. } => { 177 Expr::Block { statements, tail, id, label } => {
150 let scope = scopes.new_block_scope(scope, *id); 178 let scope = scopes.new_block_scope(scope, *id, make_label(label));
151 // Overwrite the old scope for the block expr, so that every block scope can be found 179 // 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). 180 // via the block itself (important for blocks that only contain items, no expressions).
153 scopes.set_scope(expr, scope); 181 scopes.set_scope(expr, scope);
154 compute_block_scopes(&statements, *tail, body, scopes, scope); 182 compute_block_scopes(statements, *tail, body, scopes, scope);
155 } 183 }
156 Expr::For { iterable, pat, body: body_expr, .. } => { 184 Expr::For { iterable, pat, body: body_expr, label } => {
157 compute_expr_scopes(*iterable, body, scopes, scope); 185 compute_expr_scopes(*iterable, body, scopes, scope);
158 let scope = scopes.new_scope(scope); 186 let scope = scopes.new_labeled_scope(scope, make_label(label));
159 scopes.add_bindings(body, scope, *pat); 187 scopes.add_bindings(body, scope, *pat);
160 compute_expr_scopes(*body_expr, body, scopes, scope); 188 compute_expr_scopes(*body_expr, body, scopes, scope);
161 } 189 }
190 Expr::While { condition, body: body_expr, label } => {
191 let scope = scopes.new_labeled_scope(scope, make_label(label));
192 compute_expr_scopes(*condition, body, scopes, scope);
193 compute_expr_scopes(*body_expr, body, scopes, scope);
194 }
195 Expr::Loop { body: body_expr, label } => {
196 let scope = scopes.new_labeled_scope(scope, make_label(label));
197 compute_expr_scopes(*body_expr, body, scopes, scope);
198 }
162 Expr::Lambda { args, body: body_expr, .. } => { 199 Expr::Lambda { args, body: body_expr, .. } => {
163 let scope = scopes.new_scope(scope); 200 let scope = scopes.new_scope(scope);
164 scopes.add_params_bindings(body, scope, &args); 201 scopes.add_params_bindings(body, scope, &args);
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index de08e2737..109d3552f 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -18,7 +18,8 @@ use crate::{
18/// *from where* you're referring to the item, hence the `from` parameter. 18/// *from where* you're referring to the item, hence the `from` parameter.
19pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 19pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
20 let _p = profile::span("find_path"); 20 let _p = profile::span("find_path");
21 find_path_inner(db, item, from, MAX_PATH_LEN, None) 21 let mut visited_modules = FxHashSet::default();
22 find_path_inner(db, item, from, MAX_PATH_LEN, None, &mut visited_modules)
22} 23}
23 24
24pub fn find_path_prefixed( 25pub fn find_path_prefixed(
@@ -28,7 +29,8 @@ pub fn find_path_prefixed(
28 prefix_kind: PrefixKind, 29 prefix_kind: PrefixKind,
29) -> Option<ModPath> { 30) -> Option<ModPath> {
30 let _p = profile::span("find_path_prefixed"); 31 let _p = profile::span("find_path_prefixed");
31 find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind)) 32 let mut visited_modules = FxHashSet::default();
33 find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind), &mut visited_modules)
32} 34}
33 35
34const MAX_PATH_LEN: usize = 15; 36const MAX_PATH_LEN: usize = 15;
@@ -97,6 +99,7 @@ fn find_path_inner(
97 from: ModuleId, 99 from: ModuleId,
98 max_len: usize, 100 max_len: usize,
99 mut prefixed: Option<PrefixKind>, 101 mut prefixed: Option<PrefixKind>,
102 visited_modules: &mut FxHashSet<ModuleId>,
100) -> Option<ModPath> { 103) -> Option<ModPath> {
101 if max_len == 0 { 104 if max_len == 0 {
102 return None; 105 return None;
@@ -176,15 +179,18 @@ fn find_path_inner(
176 if item.krate(db) == Some(from.krate) { 179 if item.krate(db) == Some(from.krate) {
177 // Item was defined in the same crate that wants to import it. It cannot be found in any 180 // Item was defined in the same crate that wants to import it. It cannot be found in any
178 // dependency in this case. 181 // dependency in this case.
179 182 for (module_id, name) in find_local_import_locations(db, item, from) {
180 let local_imports = find_local_import_locations(db, item, from); 183 if !visited_modules.insert(module_id) {
181 for (module_id, name) in local_imports { 184 cov_mark::hit!(recursive_imports);
185 continue;
186 }
182 if let Some(mut path) = find_path_inner( 187 if let Some(mut path) = find_path_inner(
183 db, 188 db,
184 ItemInNs::Types(ModuleDefId::ModuleId(module_id)), 189 ItemInNs::Types(ModuleDefId::ModuleId(module_id)),
185 from, 190 from,
186 best_path_len - 1, 191 best_path_len - 1,
187 prefixed, 192 prefixed,
193 visited_modules,
188 ) { 194 ) {
189 path.push_segment(name); 195 path.push_segment(name);
190 196
@@ -213,6 +219,7 @@ fn find_path_inner(
213 from, 219 from,
214 best_path_len - 1, 220 best_path_len - 1,
215 prefixed, 221 prefixed,
222 visited_modules,
216 )?; 223 )?;
217 cov_mark::hit!(partially_imported); 224 cov_mark::hit!(partially_imported);
218 path.push_segment(info.path.segments.last().unwrap().clone()); 225 path.push_segment(info.path.segments.last().unwrap().clone());
@@ -391,8 +398,15 @@ mod tests {
391 .take_types() 398 .take_types()
392 .unwrap(); 399 .unwrap();
393 400
394 let found_path = 401 let mut visited_modules = FxHashSet::default();
395 find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind); 402 let found_path = find_path_inner(
403 &db,
404 ItemInNs::Types(resolved),
405 module,
406 MAX_PATH_LEN,
407 prefix_kind,
408 &mut visited_modules,
409 );
396 assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); 410 assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind);
397 } 411 }
398 412
@@ -878,4 +892,32 @@ mod tests {
878 "self::module::CompleteMe", 892 "self::module::CompleteMe",
879 ) 893 )
880 } 894 }
895
896 #[test]
897 fn recursive_pub_mod_reexport() {
898 cov_mark::check!(recursive_imports);
899 check_found_path(
900 r#"
901fn main() {
902 let _ = 22_i32.as_name$0();
903}
904
905pub mod name {
906 pub trait AsName {
907 fn as_name(&self) -> String;
908 }
909 impl AsName for i32 {
910 fn as_name(&self) -> String {
911 format!("Name: {}", self)
912 }
913 }
914 pub use crate::name;
915}
916"#,
917 "name::AsName",
918 "name::AsName",
919 "crate::name::AsName",
920 "self::name::AsName",
921 );
922 }
881} 923}
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 0d3a0b54f..9e8e4e9ec 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -322,6 +322,23 @@ impl DefMap {
322 (res.resolved_def, res.segment_index) 322 (res.resolved_def, res.segment_index)
323 } 323 }
324 324
325 pub(crate) fn resolve_path_locally(
326 &self,
327 db: &dyn DefDatabase,
328 original_module: LocalModuleId,
329 path: &ModPath,
330 shadow: BuiltinShadowMode,
331 ) -> (PerNs, Option<usize>) {
332 let res = self.resolve_path_fp_with_macro_single(
333 db,
334 ResolveMode::Other,
335 original_module,
336 path,
337 shadow,
338 );
339 (res.resolved_def, res.segment_index)
340 }
341
325 /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. 342 /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
326 /// 343 ///
327 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns 344 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 46a3c60cd..d8fabe49b 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -91,7 +91,6 @@ pub(super) fn collect_defs(
91 resolved_imports: Vec::new(), 91 resolved_imports: Vec::new(),
92 92
93 unexpanded_macros: Vec::new(), 93 unexpanded_macros: Vec::new(),
94 unexpanded_attribute_macros: Vec::new(),
95 mod_dirs: FxHashMap::default(), 94 mod_dirs: FxHashMap::default(),
96 cfg_options, 95 cfg_options,
97 proc_macros, 96 proc_macros,
@@ -202,15 +201,14 @@ struct ImportDirective {
202#[derive(Clone, Debug, Eq, PartialEq)] 201#[derive(Clone, Debug, Eq, PartialEq)]
203struct MacroDirective { 202struct MacroDirective {
204 module_id: LocalModuleId, 203 module_id: LocalModuleId,
205 ast_id: AstIdWithPath<ast::MacroCall>,
206 legacy: Option<MacroCallId>,
207 depth: usize, 204 depth: usize,
205 kind: MacroDirectiveKind,
208} 206}
209 207
210#[derive(Clone, Debug, Eq, PartialEq)] 208#[derive(Clone, Debug, Eq, PartialEq)]
211struct DeriveDirective { 209enum MacroDirectiveKind {
212 module_id: LocalModuleId, 210 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, legacy: Option<MacroCallId> },
213 ast_id: AstIdWithPath<ast::Item>, 211 Derive { ast_id: AstIdWithPath<ast::Item> },
214} 212}
215 213
216struct DefData<'a> { 214struct DefData<'a> {
@@ -228,7 +226,6 @@ struct DefCollector<'a> {
228 unresolved_imports: Vec<ImportDirective>, 226 unresolved_imports: Vec<ImportDirective>,
229 resolved_imports: Vec<ImportDirective>, 227 resolved_imports: Vec<ImportDirective>,
230 unexpanded_macros: Vec<MacroDirective>, 228 unexpanded_macros: Vec<MacroDirective>,
231 unexpanded_attribute_macros: Vec<DeriveDirective>,
232 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 229 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
233 cfg_options: &'a CfgOptions, 230 cfg_options: &'a CfgOptions,
234 /// List of procedural macros defined by this crate. This is read from the dynamic library 231 /// List of procedural macros defined by this crate. This is read from the dynamic library
@@ -782,60 +779,58 @@ impl DefCollector<'_> {
782 779
783 fn resolve_macros(&mut self) -> ReachedFixedPoint { 780 fn resolve_macros(&mut self) -> ReachedFixedPoint {
784 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 781 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
785 let mut attribute_macros =
786 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
787 let mut resolved = Vec::new(); 782 let mut resolved = Vec::new();
788 let mut res = ReachedFixedPoint::Yes; 783 let mut res = ReachedFixedPoint::Yes;
789 macros.retain(|directive| { 784 macros.retain(|directive| {
790 if let Some(call_id) = directive.legacy { 785 match &directive.kind {
791 res = ReachedFixedPoint::No; 786 MacroDirectiveKind::FnLike { ast_id, legacy } => {
792 resolved.push((directive.module_id, call_id, directive.depth)); 787 if let Some(call_id) = legacy {
793 return false; 788 res = ReachedFixedPoint::No;
794 } 789 resolved.push((directive.module_id, *call_id, directive.depth));
790 return false;
791 }
795 792
796 match macro_call_as_call_id( 793 match macro_call_as_call_id(
797 &directive.ast_id, 794 ast_id,
798 self.db,
799 self.def_map.krate,
800 |path| {
801 let resolved_res = self.def_map.resolve_path_fp_with_macro(
802 self.db, 795 self.db,
803 ResolveMode::Other, 796 self.def_map.krate,
804 directive.module_id, 797 |path| {
805 &path, 798 let resolved_res = self.def_map.resolve_path_fp_with_macro(
806 BuiltinShadowMode::Module, 799 self.db,
807 ); 800 ResolveMode::Other,
808 resolved_res.resolved_def.take_macros() 801 directive.module_id,
809 }, 802 &path,
810 &mut |_err| (), 803 BuiltinShadowMode::Module,
811 ) { 804 );
812 Ok(Ok(call_id)) => { 805 resolved_res.resolved_def.take_macros()
813 resolved.push((directive.module_id, call_id, directive.depth)); 806 },
814 res = ReachedFixedPoint::No; 807 &mut |_err| (),
815 return false; 808 ) {
809 Ok(Ok(call_id)) => {
810 resolved.push((directive.module_id, call_id, directive.depth));
811 res = ReachedFixedPoint::No;
812 return false;
813 }
814 Err(UnresolvedMacro) | Ok(Err(_)) => {}
815 }
816 } 816 }
817 Err(UnresolvedMacro) | Ok(Err(_)) => {} 817 MacroDirectiveKind::Derive { ast_id } => {
818 } 818 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| {
819 819 self.resolve_derive_macro(directive.module_id, &path)
820 true 820 }) {
821 }); 821 Ok(call_id) => {
822 attribute_macros.retain(|directive| { 822 resolved.push((directive.module_id, call_id, 0));
823 match derive_macro_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { 823 res = ReachedFixedPoint::No;
824 self.resolve_derive_macro(&directive, &path) 824 return false;
825 }) { 825 }
826 Ok(call_id) => { 826 Err(UnresolvedMacro) => (),
827 resolved.push((directive.module_id, call_id, 0)); 827 }
828 res = ReachedFixedPoint::No;
829 return false;
830 } 828 }
831 Err(UnresolvedMacro) => (),
832 } 829 }
833 830
834 true 831 true
835 }); 832 });
836
837 self.unexpanded_macros = macros; 833 self.unexpanded_macros = macros;
838 self.unexpanded_attribute_macros = attribute_macros;
839 834
840 for (module_id, macro_call_id, depth) in resolved { 835 for (module_id, macro_call_id, depth) in resolved {
841 self.collect_macro_expansion(module_id, macro_call_id, depth); 836 self.collect_macro_expansion(module_id, macro_call_id, depth);
@@ -844,15 +839,11 @@ impl DefCollector<'_> {
844 res 839 res
845 } 840 }
846 841
847 fn resolve_derive_macro( 842 fn resolve_derive_macro(&self, module: LocalModuleId, path: &ModPath) -> Option<MacroDefId> {
848 &self,
849 directive: &DeriveDirective,
850 path: &ModPath,
851 ) -> Option<MacroDefId> {
852 let resolved_res = self.def_map.resolve_path_fp_with_macro( 843 let resolved_res = self.def_map.resolve_path_fp_with_macro(
853 self.db, 844 self.db,
854 ResolveMode::Other, 845 ResolveMode::Other,
855 directive.module_id, 846 module,
856 &path, 847 &path,
857 BuiltinShadowMode::Module, 848 BuiltinShadowMode::Module,
858 ); 849 );
@@ -912,33 +903,35 @@ impl DefCollector<'_> {
912 // Emit diagnostics for all remaining unexpanded macros. 903 // Emit diagnostics for all remaining unexpanded macros.
913 904
914 for directive in &self.unexpanded_macros { 905 for directive in &self.unexpanded_macros {
915 let mut error = None; 906 match &directive.kind {
916 match macro_call_as_call_id( 907 MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id(
917 &directive.ast_id, 908 ast_id,
918 self.db, 909 self.db,
919 self.def_map.krate, 910 self.def_map.krate,
920 |path| { 911 |path| {
921 let resolved_res = self.def_map.resolve_path_fp_with_macro( 912 let resolved_res = self.def_map.resolve_path_fp_with_macro(
922 self.db, 913 self.db,
923 ResolveMode::Other, 914 ResolveMode::Other,
924 directive.module_id, 915 directive.module_id,
925 &path, 916 &path,
926 BuiltinShadowMode::Module, 917 BuiltinShadowMode::Module,
927 ); 918 );
928 resolved_res.resolved_def.take_macros() 919 resolved_res.resolved_def.take_macros()
929 }, 920 },
930 &mut |e| { 921 &mut |_| (),
931 error.get_or_insert(e); 922 ) {
923 Ok(_) => (),
924 Err(UnresolvedMacro) => {
925 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
926 directive.module_id,
927 ast_id.ast_id,
928 ));
929 }
932 }, 930 },
933 ) { 931 MacroDirectiveKind::Derive { .. } => {
934 Ok(_) => (), 932 // FIXME: we might want to diagnose this too
935 Err(UnresolvedMacro) => {
936 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
937 directive.module_id,
938 directive.ast_id.ast_id,
939 ));
940 } 933 }
941 }; 934 }
942 } 935 }
943 936
944 // Emit diagnostics for all remaining unresolved imports. 937 // Emit diagnostics for all remaining unresolved imports.
@@ -1380,9 +1373,11 @@ impl ModCollector<'_, '_> {
1380 Some(derive_macros) => { 1373 Some(derive_macros) => {
1381 for path in derive_macros { 1374 for path in derive_macros {
1382 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); 1375 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1383 self.def_collector 1376 self.def_collector.unexpanded_macros.push(MacroDirective {
1384 .unexpanded_attribute_macros 1377 module_id: self.module_id,
1385 .push(DeriveDirective { module_id: self.module_id, ast_id }); 1378 depth: self.macro_depth + 1,
1379 kind: MacroDirectiveKind::Derive { ast_id },
1380 });
1386 } 1381 }
1387 } 1382 }
1388 None => { 1383 None => {
@@ -1467,12 +1462,13 @@ impl ModCollector<'_, '_> {
1467 }, 1462 },
1468 ) { 1463 ) {
1469 Ok(Ok(macro_call_id)) => { 1464 Ok(Ok(macro_call_id)) => {
1470 self.def_collector.unexpanded_macros.push(MacroDirective { 1465 // Legacy macros need to be expanded immediately, so that any macros they produce
1471 module_id: self.module_id, 1466 // are in scope.
1472 ast_id, 1467 self.def_collector.collect_macro_expansion(
1473 legacy: Some(macro_call_id), 1468 self.module_id,
1474 depth: self.macro_depth + 1, 1469 macro_call_id,
1475 }); 1470 self.macro_depth + 1,
1471 );
1476 1472
1477 return; 1473 return;
1478 } 1474 }
@@ -1496,9 +1492,8 @@ impl ModCollector<'_, '_> {
1496 1492
1497 self.def_collector.unexpanded_macros.push(MacroDirective { 1493 self.def_collector.unexpanded_macros.push(MacroDirective {
1498 module_id: self.module_id, 1494 module_id: self.module_id,
1499 ast_id,
1500 legacy: None,
1501 depth: self.macro_depth + 1, 1495 depth: self.macro_depth + 1,
1496 kind: MacroDirectiveKind::FnLike { ast_id, legacy: None },
1502 }); 1497 });
1503 } 1498 }
1504 1499
@@ -1541,7 +1536,6 @@ mod tests {
1541 unresolved_imports: Vec::new(), 1536 unresolved_imports: Vec::new(),
1542 resolved_imports: Vec::new(), 1537 resolved_imports: Vec::new(),
1543 unexpanded_macros: Vec::new(), 1538 unexpanded_macros: Vec::new(),
1544 unexpanded_attribute_macros: Vec::new(),
1545 mod_dirs: FxHashMap::default(), 1539 mod_dirs: FxHashMap::default(),
1546 cfg_options: &CfgOptions::default(), 1540 cfg_options: &CfgOptions::default(),
1547 proc_macros: Default::default(), 1541 proc_macros: Default::default(),
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs
index d5de9899c..d9cec0e27 100644
--- a/crates/hir_def/src/nameres/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/mod_resolution.rs
@@ -62,7 +62,7 @@ impl ModDir {
62 name: &Name, 62 name: &Name,
63 attr_path: Option<&SmolStr>, 63 attr_path: Option<&SmolStr>,
64 ) -> Result<(FileId, bool, ModDir), String> { 64 ) -> Result<(FileId, bool, ModDir), String> {
65 let file_id = file_id.original_file(db.upcast()); 65 let orig_file_id = file_id.original_file(db.upcast());
66 66
67 let mut candidate_files = Vec::new(); 67 let mut candidate_files = Vec::new();
68 match attr_path { 68 match attr_path {
@@ -70,13 +70,18 @@ impl ModDir {
70 candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) 70 candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
71 } 71 }
72 None => { 72 None => {
73 candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); 73 if file_id.is_include_macro(db.upcast()) {
74 candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); 74 candidate_files.push(format!("{}.rs", name));
75 candidate_files.push(format!("{}/mod.rs", name));
76 } else {
77 candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
78 candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
79 }
75 } 80 }
76 }; 81 };
77 82
78 for candidate in candidate_files.iter() { 83 for candidate in candidate_files.iter() {
79 let path = AnchoredPath { anchor: file_id, path: candidate.as_str() }; 84 let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
80 if let Some(file_id) = db.resolve_path(path) { 85 if let Some(file_id) = db.resolve_path(path) {
81 let is_mod_rs = candidate.ends_with("/mod.rs"); 86 let is_mod_rs = candidate.ends_with("/mod.rs");
82 87
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index db459b1ed..60471937c 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -156,7 +156,7 @@ impl DefMap {
156 } 156 }
157 } 157 }
158 158
159 fn resolve_path_fp_with_macro_single( 159 pub(super) fn resolve_path_fp_with_macro_single(
160 &self, 160 &self,
161 db: &dyn DefDatabase, 161 db: &dyn DefDatabase,
162 mode: ResolveMode, 162 mode: ResolveMode,
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index d59d3c0db..6d3cb8d7a 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -713,6 +713,27 @@ b! { static = #[] ();}
713} 713}
714 714
715#[test] 715#[test]
716fn macros_defining_macros() {
717 check(
718 r#"
719macro_rules! item {
720 ($item:item) => { $item }
721}
722
723item! {
724 macro_rules! indirect_macro { () => { struct S {} } }
725}
726
727indirect_macro!();
728 "#,
729 expect![[r#"
730 crate
731 S: t
732 "#]],
733 );
734}
735
736#[test]
716fn resolves_proc_macros() { 737fn resolves_proc_macros() {
717 check( 738 check(
718 r" 739 r"
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 42736171e..a73585ee7 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -12,7 +12,7 @@ use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
14 db::DefDatabase, 14 db::DefDatabase,
15 expr::{ExprId, PatId}, 15 expr::{ExprId, LabelId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, 17 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
18 nameres::DefMap, 18 nameres::DefMap,
@@ -409,6 +409,7 @@ pub enum ScopeDef {
409 AdtSelfType(AdtId), 409 AdtSelfType(AdtId),
410 GenericParam(GenericParamId), 410 GenericParam(GenericParamId),
411 Local(PatId), 411 Local(PatId),
412 Label(LabelId),
412} 413}
413 414
414impl Scope { 415impl Scope {
@@ -470,6 +471,9 @@ impl Scope {
470 f(name![Self], ScopeDef::AdtSelfType(*i)); 471 f(name![Self], ScopeDef::AdtSelfType(*i));
471 } 472 }
472 Scope::ExprScope(scope) => { 473 Scope::ExprScope(scope) => {
474 if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) {
475 f(name, ScopeDef::Label(label))
476 }
473 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { 477 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
474 f(e.name().clone(), ScopeDef::Local(e.pat())); 478 f(e.name().clone(), ScopeDef::Local(e.pat()));
475 }); 479 });
@@ -544,7 +548,7 @@ impl ModuleItemMap {
544 path: &ModPath, 548 path: &ModPath,
545 ) -> Option<ResolveValueResult> { 549 ) -> Option<ResolveValueResult> {
546 let (module_def, idx) = 550 let (module_def, idx) =
547 self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); 551 self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
548 match idx { 552 match idx {
549 None => { 553 None => {
550 let value = to_value_ns(module_def)?; 554 let value = to_value_ns(module_def)?;
@@ -574,7 +578,7 @@ impl ModuleItemMap {
574 path: &ModPath, 578 path: &ModPath,
575 ) -> Option<(TypeNs, Option<usize>)> { 579 ) -> Option<(TypeNs, Option<usize>)> {
576 let (module_def, idx) = 580 let (module_def, idx) =
577 self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); 581 self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
578 let res = to_type_ns(module_def)?; 582 let res = to_type_ns(module_def)?;
579 Some((res, idx)) 583 Some((res, idx))
580 } 584 }
@@ -623,8 +627,18 @@ pub trait HasResolver: Copy {
623 627
624impl HasResolver for ModuleId { 628impl HasResolver for ModuleId {
625 fn resolver(self, db: &dyn DefDatabase) -> Resolver { 629 fn resolver(self, db: &dyn DefDatabase) -> Resolver {
626 let def_map = self.def_map(db); 630 let mut def_map = self.def_map(db);
627 Resolver::default().push_module_scope(def_map, self.local_id) 631 let mut modules = Vec::new();
632 modules.push((def_map.clone(), self.local_id));
633 while let Some(parent) = def_map.parent() {
634 def_map = parent.def_map(db);
635 modules.push((def_map.clone(), parent.local_id));
636 }
637 let mut resolver = Resolver::default();
638 for (def_map, module) in modules.into_iter().rev() {
639 resolver = resolver.push_module_scope(def_map, module);
640 }
641 resolver
628 } 642 }
629} 643}
630 644