aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r--crates/hir_def/src/nameres/collector.rs418
1 files changed, 238 insertions, 180 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 3e99c8773..4c3993ff0 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -3,8 +3,11 @@
3//! `DefCollector::collect` contains the fixed-point iteration loop which 3//! `DefCollector::collect` contains the fixed-point iteration loop which
4//! resolves imports and expands macros. 4//! resolves imports and expands macros.
5 5
6use std::iter;
7
6use base_db::{CrateId, FileId, ProcMacroId}; 8use base_db::{CrateId, FileId, ProcMacroId};
7use cfg::CfgOptions; 9use cfg::CfgOptions;
10use hir_expand::InFile;
8use hir_expand::{ 11use hir_expand::{
9 ast_id_map::FileAstId, 12 ast_id_map::FileAstId,
10 builtin_derive::find_builtin_derive, 13 builtin_derive::find_builtin_derive,
@@ -14,6 +17,7 @@ use hir_expand::{
14 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 17 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
15}; 18};
16use rustc_hash::FxHashMap; 19use rustc_hash::FxHashMap;
20use rustc_hash::FxHashSet;
17use syntax::ast; 21use syntax::ast;
18use test_utils::mark; 22use test_utils::mark;
19 23
@@ -21,9 +25,7 @@ use crate::{
21 attr::Attrs, 25 attr::Attrs,
22 db::DefDatabase, 26 db::DefDatabase,
23 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
24 item_tree::{ 28 item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind},
25 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
26 },
27 nameres::{ 29 nameres::{
28 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 30 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
29 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 31 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -112,6 +114,12 @@ impl PartialResolvedImport {
112} 114}
113 115
114#[derive(Clone, Debug, Eq, PartialEq)] 116#[derive(Clone, Debug, Eq, PartialEq)]
117enum ImportSource {
118 Import(ItemTreeId<item_tree::Import>),
119 ExternCrate(ItemTreeId<item_tree::ExternCrate>),
120}
121
122#[derive(Clone, Debug, Eq, PartialEq)]
115struct Import { 123struct Import {
116 pub path: ModPath, 124 pub path: ModPath,
117 pub alias: Option<ImportAlias>, 125 pub alias: Option<ImportAlias>,
@@ -120,11 +128,12 @@ struct Import {
120 pub is_prelude: bool, 128 pub is_prelude: bool,
121 pub is_extern_crate: bool, 129 pub is_extern_crate: bool,
122 pub is_macro_use: bool, 130 pub is_macro_use: bool,
131 source: ImportSource,
123} 132}
124 133
125impl Import { 134impl Import {
126 fn from_use(tree: &ItemTree, id: FileItemTreeId<item_tree::Import>) -> Self { 135 fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self {
127 let it = &tree[id]; 136 let it = &tree[id.value];
128 let visibility = &tree[it.visibility]; 137 let visibility = &tree[it.visibility];
129 Self { 138 Self {
130 path: it.path.clone(), 139 path: it.path.clone(),
@@ -134,20 +143,22 @@ impl Import {
134 is_prelude: it.is_prelude, 143 is_prelude: it.is_prelude,
135 is_extern_crate: false, 144 is_extern_crate: false,
136 is_macro_use: false, 145 is_macro_use: false,
146 source: ImportSource::Import(id),
137 } 147 }
138 } 148 }
139 149
140 fn from_extern_crate(tree: &ItemTree, id: FileItemTreeId<item_tree::ExternCrate>) -> Self { 150 fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self {
141 let it = &tree[id]; 151 let it = &tree[id.value];
142 let visibility = &tree[it.visibility]; 152 let visibility = &tree[it.visibility];
143 Self { 153 Self {
144 path: it.path.clone(), 154 path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
145 alias: it.alias.clone(), 155 alias: it.alias.clone(),
146 visibility: visibility.clone(), 156 visibility: visibility.clone(),
147 is_glob: false, 157 is_glob: false,
148 is_prelude: false, 158 is_prelude: false,
149 is_extern_crate: true, 159 is_extern_crate: true,
150 is_macro_use: it.is_macro_use, 160 is_macro_use: it.is_macro_use,
161 source: ImportSource::ExternCrate(id),
151 } 162 }
152 } 163 }
153} 164}
@@ -245,9 +256,10 @@ impl DefCollector<'_> {
245 256
246 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 257 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
247 // show unresolved imports in completion, etc 258 // show unresolved imports in completion, etc
248 for directive in unresolved_imports { 259 for directive in &unresolved_imports {
249 self.record_resolved_import(&directive) 260 self.record_resolved_import(directive)
250 } 261 }
262 self.unresolved_imports = unresolved_imports;
251 263
252 // Record proc-macros 264 // Record proc-macros
253 self.collect_proc_macro(); 265 self.collect_proc_macro();
@@ -261,7 +273,7 @@ impl DefCollector<'_> {
261 let macro_id = MacroDefId { 273 let macro_id = MacroDefId {
262 ast_id: None, 274 ast_id: None,
263 krate: Some(krate), 275 krate: Some(krate),
264 kind: MacroDefKind::CustomDerive(expander), 276 kind: MacroDefKind::ProcMacro(expander),
265 local_inner: false, 277 local_inner: false,
266 }; 278 };
267 279
@@ -346,20 +358,15 @@ impl DefCollector<'_> {
346 fn import_macros_from_extern_crate( 358 fn import_macros_from_extern_crate(
347 &mut self, 359 &mut self,
348 current_module_id: LocalModuleId, 360 current_module_id: LocalModuleId,
349 import: &item_tree::ExternCrate, 361 extern_crate: &item_tree::ExternCrate,
350 ) { 362 ) {
351 log::debug!( 363 log::debug!(
352 "importing macros from extern crate: {:?} ({:?})", 364 "importing macros from extern crate: {:?} ({:?})",
353 import, 365 extern_crate,
354 self.def_map.edition, 366 self.def_map.edition,
355 ); 367 );
356 368
357 let res = self.def_map.resolve_name_in_extern_prelude( 369 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name);
358 &import
359 .path
360 .as_ident()
361 .expect("extern crate should have been desugared to one-element path"),
362 );
363 370
364 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 371 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
365 mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 372 mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -420,7 +427,11 @@ impl DefCollector<'_> {
420 .as_ident() 427 .as_ident()
421 .expect("extern crate should have been desugared to one-element path"), 428 .expect("extern crate should have been desugared to one-element path"),
422 ); 429 );
423 PartialResolvedImport::Resolved(res) 430 if res.is_none() {
431 PartialResolvedImport::Unresolved
432 } else {
433 PartialResolvedImport::Resolved(res)
434 }
424 } else { 435 } else {
425 let res = self.def_map.resolve_path_fp_with_macro( 436 let res = self.def_map.resolve_path_fp_with_macro(
426 self.db, 437 self.db,
@@ -774,7 +785,51 @@ impl DefCollector<'_> {
774 .collect(item_tree.top_level_items()); 785 .collect(item_tree.top_level_items());
775 } 786 }
776 787
777 fn finish(self) -> CrateDefMap { 788 fn finish(mut self) -> CrateDefMap {
789 // Emit diagnostics for all remaining unresolved imports.
790
791 // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
792 // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
793 // crate names. Then we emit diagnostics for unresolved imports, but only if the import
794 // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
795 // heuristic, but it works in practice.
796 let mut diagnosed_extern_crates = FxHashSet::default();
797 for directive in &self.unresolved_imports {
798 if let ImportSource::ExternCrate(krate) = directive.import.source {
799 let item_tree = self.db.item_tree(krate.file_id);
800 let extern_crate = &item_tree[krate.value];
801
802 diagnosed_extern_crates.insert(extern_crate.name.clone());
803
804 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
805 directive.module_id,
806 InFile::new(krate.file_id, extern_crate.ast_id),
807 ));
808 }
809 }
810
811 for directive in &self.unresolved_imports {
812 if let ImportSource::Import(import) = &directive.import.source {
813 let item_tree = self.db.item_tree(import.file_id);
814 let import_data = &item_tree[import.value];
815
816 match (import_data.path.segments.first(), &import_data.path.kind) {
817 (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
818 if diagnosed_extern_crates.contains(krate) {
819 continue;
820 }
821 }
822 _ => {}
823 }
824
825 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
826 directive.module_id,
827 InFile::new(import.file_id, import_data.ast_id),
828 import_data.index,
829 ));
830 }
831 }
832
778 self.def_map 833 self.def_map
779 } 834 }
780} 835}
@@ -819,179 +874,184 @@ impl ModCollector<'_, '_> {
819 874
820 for &item in items { 875 for &item in items {
821 let attrs = self.item_tree.attrs(item.into()); 876 let attrs = self.item_tree.attrs(item.into());
822 if self.is_cfg_enabled(attrs) { 877 if !self.is_cfg_enabled(attrs) {
823 let module = 878 continue;
824 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; 879 }
825 let container = ContainerId::ModuleId(module); 880 let module =
826 881 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
827 let mut def = None; 882 let container = ContainerId::ModuleId(module);
828 match item { 883
829 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), 884 let mut def = None;
830 ModItem::Import(import_id) => { 885 match item {
831 self.def_collector.unresolved_imports.push(ImportDirective { 886 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs),
832 module_id: self.module_id, 887 ModItem::Import(import_id) => {
833 import: Import::from_use(&self.item_tree, import_id), 888 self.def_collector.unresolved_imports.push(ImportDirective {
834 status: PartialResolvedImport::Unresolved, 889 module_id: self.module_id,
835 }) 890 import: Import::from_use(
836 } 891 &self.item_tree,
837 ModItem::ExternCrate(import_id) => { 892 InFile::new(self.file_id, import_id),
838 self.def_collector.unresolved_imports.push(ImportDirective { 893 ),
839 module_id: self.module_id, 894 status: PartialResolvedImport::Unresolved,
840 import: Import::from_extern_crate(&self.item_tree, import_id), 895 })
841 status: PartialResolvedImport::Unresolved, 896 }
842 }) 897 ModItem::ExternCrate(import_id) => {
843 } 898 self.def_collector.unresolved_imports.push(ImportDirective {
844 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]), 899 module_id: self.module_id,
845 ModItem::Impl(imp) => { 900 import: Import::from_extern_crate(
846 let module = ModuleId { 901 &self.item_tree,
847 krate: self.def_collector.def_map.krate, 902 InFile::new(self.file_id, import_id),
848 local_id: self.module_id, 903 ),
849 }; 904 status: PartialResolvedImport::Unresolved,
850 let container = ContainerId::ModuleId(module); 905 })
851 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } 906 }
852 .intern(self.def_collector.db); 907 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]),
853 self.def_collector.def_map.modules[self.module_id] 908 ModItem::Impl(imp) => {
854 .scope 909 let module = ModuleId {
855 .define_impl(impl_id) 910 krate: self.def_collector.def_map.krate,
856 } 911 local_id: self.module_id,
857 ModItem::Function(id) => { 912 };
858 let func = &self.item_tree[id]; 913 let container = ContainerId::ModuleId(module);
859 def = Some(DefData { 914 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) }
860 id: FunctionLoc { 915 .intern(self.def_collector.db);
861 container: container.into(), 916 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
862 id: ItemTreeId::new(self.file_id, id), 917 }
863 } 918 ModItem::Function(id) => {
864 .intern(self.def_collector.db) 919 let func = &self.item_tree[id];
865 .into(), 920 def = Some(DefData {
866 name: &func.name, 921 id: FunctionLoc {
867 visibility: &self.item_tree[func.visibility], 922 container: container.into(),
868 has_constructor: false, 923 id: ItemTreeId::new(self.file_id, id),
869 }); 924 }
870 } 925 .intern(self.def_collector.db)
871 ModItem::Struct(id) => { 926 .into(),
872 let it = &self.item_tree[id]; 927 name: &func.name,
873 928 visibility: &self.item_tree[func.visibility],
874 // FIXME: check attrs to see if this is an attribute macro invocation; 929 has_constructor: false,
875 // in which case we don't add the invocation, just a single attribute 930 });
876 // macro invocation 931 }
877 self.collect_derives(attrs, it.ast_id.upcast()); 932 ModItem::Struct(id) => {
878 933 let it = &self.item_tree[id];
879 def = Some(DefData {
880 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
881 .intern(self.def_collector.db)
882 .into(),
883 name: &it.name,
884 visibility: &self.item_tree[it.visibility],
885 has_constructor: it.kind != StructDefKind::Record,
886 });
887 }
888 ModItem::Union(id) => {
889 let it = &self.item_tree[id];
890 934
891 // FIXME: check attrs to see if this is an attribute macro invocation; 935 // FIXME: check attrs to see if this is an attribute macro invocation;
892 // in which case we don't add the invocation, just a single attribute 936 // in which case we don't add the invocation, just a single attribute
893 // macro invocation 937 // macro invocation
894 self.collect_derives(attrs, it.ast_id.upcast()); 938 self.collect_derives(attrs, it.ast_id.upcast());
895 939
896 def = Some(DefData { 940 def = Some(DefData {
897 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } 941 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
898 .intern(self.def_collector.db) 942 .intern(self.def_collector.db)
899 .into(), 943 .into(),
900 name: &it.name, 944 name: &it.name,
901 visibility: &self.item_tree[it.visibility], 945 visibility: &self.item_tree[it.visibility],
902 has_constructor: false, 946 has_constructor: it.kind != StructDefKind::Record,
903 }); 947 });
904 } 948 }
905 ModItem::Enum(id) => { 949 ModItem::Union(id) => {
906 let it = &self.item_tree[id]; 950 let it = &self.item_tree[id];
907 951
908 // FIXME: check attrs to see if this is an attribute macro invocation; 952 // FIXME: check attrs to see if this is an attribute macro invocation;
909 // in which case we don't add the invocation, just a single attribute 953 // in which case we don't add the invocation, just a single attribute
910 // macro invocation 954 // macro invocation
911 self.collect_derives(attrs, it.ast_id.upcast()); 955 self.collect_derives(attrs, it.ast_id.upcast());
912 956
913 def = Some(DefData { 957 def = Some(DefData {
914 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } 958 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) }
915 .intern(self.def_collector.db) 959 .intern(self.def_collector.db)
916 .into(), 960 .into(),
917 name: &it.name, 961 name: &it.name,
918 visibility: &self.item_tree[it.visibility], 962 visibility: &self.item_tree[it.visibility],
919 has_constructor: false, 963 has_constructor: false,
920 }); 964 });
921 } 965 }
922 ModItem::Const(id) => { 966 ModItem::Enum(id) => {
923 let it = &self.item_tree[id]; 967 let it = &self.item_tree[id];
924
925 if let Some(name) = &it.name {
926 def = Some(DefData {
927 id: ConstLoc {
928 container: container.into(),
929 id: ItemTreeId::new(self.file_id, id),
930 }
931 .intern(self.def_collector.db)
932 .into(),
933 name,
934 visibility: &self.item_tree[it.visibility],
935 has_constructor: false,
936 });
937 }
938 }
939 ModItem::Static(id) => {
940 let it = &self.item_tree[id];
941 968
942 def = Some(DefData { 969 // FIXME: check attrs to see if this is an attribute macro invocation;
943 id: StaticLoc { container, id: ItemTreeId::new(self.file_id, id) } 970 // in which case we don't add the invocation, just a single attribute
944 .intern(self.def_collector.db) 971 // macro invocation
945 .into(), 972 self.collect_derives(attrs, it.ast_id.upcast());
946 name: &it.name,
947 visibility: &self.item_tree[it.visibility],
948 has_constructor: false,
949 });
950 }
951 ModItem::Trait(id) => {
952 let it = &self.item_tree[id];
953 973
954 def = Some(DefData { 974 def = Some(DefData {
955 id: TraitLoc { container, id: ItemTreeId::new(self.file_id, id) } 975 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) }
956 .intern(self.def_collector.db) 976 .intern(self.def_collector.db)
957 .into(), 977 .into(),
958 name: &it.name, 978 name: &it.name,
959 visibility: &self.item_tree[it.visibility], 979 visibility: &self.item_tree[it.visibility],
960 has_constructor: false, 980 has_constructor: false,
961 }); 981 });
962 } 982 }
963 ModItem::TypeAlias(id) => { 983 ModItem::Const(id) => {
964 let it = &self.item_tree[id]; 984 let it = &self.item_tree[id];
965 985
986 if let Some(name) = &it.name {
966 def = Some(DefData { 987 def = Some(DefData {
967 id: TypeAliasLoc { 988 id: ConstLoc {
968 container: container.into(), 989 container: container.into(),
969 id: ItemTreeId::new(self.file_id, id), 990 id: ItemTreeId::new(self.file_id, id),
970 } 991 }
971 .intern(self.def_collector.db) 992 .intern(self.def_collector.db)
972 .into(), 993 .into(),
973 name: &it.name, 994 name,
974 visibility: &self.item_tree[it.visibility], 995 visibility: &self.item_tree[it.visibility],
975 has_constructor: false, 996 has_constructor: false,
976 }); 997 });
977 } 998 }
978 } 999 }
1000 ModItem::Static(id) => {
1001 let it = &self.item_tree[id];
979 1002
980 if let Some(DefData { id, name, visibility, has_constructor }) = def { 1003 def = Some(DefData {
981 self.def_collector.def_map.modules[self.module_id].scope.define_def(id); 1004 id: StaticLoc { container, id: ItemTreeId::new(self.file_id, id) }
982 let vis = self 1005 .intern(self.def_collector.db)
983 .def_collector 1006 .into(),
984 .def_map 1007 name: &it.name,
985 .resolve_visibility(self.def_collector.db, self.module_id, visibility) 1008 visibility: &self.item_tree[it.visibility],
986 .unwrap_or(Visibility::Public); 1009 has_constructor: false,
987 self.def_collector.update( 1010 });
988 self.module_id, 1011 }
989 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], 1012 ModItem::Trait(id) => {
990 vis, 1013 let it = &self.item_tree[id];
991 ImportType::Named, 1014
992 ) 1015 def = Some(DefData {
1016 id: TraitLoc { container, id: ItemTreeId::new(self.file_id, id) }
1017 .intern(self.def_collector.db)
1018 .into(),
1019 name: &it.name,
1020 visibility: &self.item_tree[it.visibility],
1021 has_constructor: false,
1022 });
1023 }
1024 ModItem::TypeAlias(id) => {
1025 let it = &self.item_tree[id];
1026
1027 def = Some(DefData {
1028 id: TypeAliasLoc {
1029 container: container.into(),
1030 id: ItemTreeId::new(self.file_id, id),
1031 }
1032 .intern(self.def_collector.db)
1033 .into(),
1034 name: &it.name,
1035 visibility: &self.item_tree[it.visibility],
1036 has_constructor: false,
1037 });
993 } 1038 }
994 } 1039 }
1040
1041 if let Some(DefData { id, name, visibility, has_constructor }) = def {
1042 self.def_collector.def_map.modules[self.module_id].scope.define_def(id);
1043 let vis = self
1044 .def_collector
1045 .def_map
1046 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1047 .unwrap_or(Visibility::Public);
1048 self.def_collector.update(
1049 self.module_id,
1050 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1051 vis,
1052 ImportType::Named,
1053 )
1054 }
995 } 1055 }
996 } 1056 }
997 1057
@@ -1051,13 +1111,11 @@ impl ModCollector<'_, '_> {
1051 self.import_all_legacy_macros(module_id); 1111 self.import_all_legacy_macros(module_id);
1052 } 1112 }
1053 } 1113 }
1054 Err(candidate) => self.def_collector.def_map.diagnostics.push( 1114 Err(candidate) => {
1055 DefDiagnostic::UnresolvedModule { 1115 self.def_collector.def_map.diagnostics.push(
1056 module: self.module_id, 1116 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidate),
1057 declaration: ast_id, 1117 );
1058 candidate, 1118 }
1059 },
1060 ),
1061 }; 1119 };
1062 } 1120 }
1063 } 1121 }