aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r--crates/hir_def/src/nameres/collector.rs82
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs12
-rw-r--r--crates/hir_def/src/nameres/tests.rs1
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs229
4 files changed, 75 insertions, 249 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 6b41921ae..6fab58f15 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
9use cfg::{CfgExpr, CfgOptions}; 9use cfg::{CfgExpr, CfgOptions};
10use hir_expand::{ 10use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_attr::find_builtin_attr,
12 builtin_derive::find_builtin_derive, 13 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 14 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 15 name::{name, AsName, Name},
@@ -23,7 +24,7 @@ use syntax::ast;
23 24
24use crate::{ 25use crate::{
25 attr::{Attr, AttrId, AttrInput, Attrs}, 26 attr::{Attr, AttrId, AttrInput, Attrs},
26 builtin_attr, 27 attr_macro_as_call_id, builtin_attr,
27 db::DefDatabase, 28 db::DefDatabase,
28 derive_macro_as_call_id, 29 derive_macro_as_call_id,
29 intern::Interned, 30 intern::Interned,
@@ -223,7 +224,7 @@ struct MacroDirective {
223enum MacroDirectiveKind { 224enum MacroDirectiveKind {
224 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, 225 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
225 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, 226 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
226 Attr { ast_id: AstIdWithPath<ast::Item>, attr: AttrId, mod_item: ModItem }, 227 Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
227} 228}
228 229
229struct DefData<'a> { 230struct DefData<'a> {
@@ -419,7 +420,7 @@ impl DefCollector<'_> {
419 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); 420 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
420 let pos = unresolved_macros.iter().position(|directive| { 421 let pos = unresolved_macros.iter().position(|directive| {
421 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { 422 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind {
422 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr); 423 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
423 424
424 let file_id = ast_id.ast_id.file_id; 425 let file_id = ast_id.ast_id.file_id;
425 let item_tree = self.db.file_item_tree(file_id); 426 let item_tree = self.db.file_item_tree(file_id);
@@ -499,7 +500,7 @@ impl DefCollector<'_> {
499 let (per_ns, _) = self.def_map.resolve_path( 500 let (per_ns, _) = self.def_map.resolve_path(
500 self.db, 501 self.db,
501 self.def_map.root, 502 self.def_map.root,
502 &path, 503 path,
503 BuiltinShadowMode::Other, 504 BuiltinShadowMode::Other,
504 ); 505 );
505 506
@@ -721,7 +722,7 @@ impl DefCollector<'_> {
721 if import.is_extern_crate { 722 if import.is_extern_crate {
722 let res = self.def_map.resolve_name_in_extern_prelude( 723 let res = self.def_map.resolve_name_in_extern_prelude(
723 self.db, 724 self.db,
724 &import 725 import
725 .path 726 .path
726 .as_ident() 727 .as_ident()
727 .expect("extern crate should have been desugared to one-element path"), 728 .expect("extern crate should have been desugared to one-element path"),
@@ -1050,7 +1051,7 @@ impl DefCollector<'_> {
1050 let file_id = ast_id.ast_id.file_id; 1051 let file_id = ast_id.ast_id.file_id;
1051 let item_tree = self.db.file_item_tree(file_id); 1052 let item_tree = self.db.file_item_tree(file_id);
1052 let mod_dir = self.mod_dirs[&directive.module_id].clone(); 1053 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1053 self.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr); 1054 self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
1054 ModCollector { 1055 ModCollector {
1055 def_collector: &mut *self, 1056 def_collector: &mut *self,
1056 macro_depth: directive.depth, 1057 macro_depth: directive.depth,
@@ -1062,13 +1063,67 @@ impl DefCollector<'_> {
1062 .collect(&[*mod_item]); 1063 .collect(&[*mod_item]);
1063 1064
1064 // Remove the original directive since we resolved it. 1065 // Remove the original directive since we resolved it.
1066 res = ReachedFixedPoint::No;
1065 return false; 1067 return false;
1066 } 1068 }
1067 } 1069 }
1068 } 1070 }
1069 1071
1072 if !self.db.enable_proc_attr_macros() {
1073 return true;
1074 }
1075
1070 // Not resolved to a derive helper, so try to resolve as a macro. 1076 // Not resolved to a derive helper, so try to resolve as a macro.
1071 // FIXME: not yet :) 1077 match attr_macro_as_call_id(
1078 ast_id,
1079 attr,
1080 self.db,
1081 self.def_map.krate,
1082 &resolver,
1083 ) {
1084 Ok(call_id) => {
1085 let loc: MacroCallLoc = self.db.lookup_intern_macro(call_id);
1086 if let MacroDefKind::ProcMacro(exp, ..) = &loc.def.kind {
1087 if exp.is_dummy() {
1088 // Proc macros that cannot be expanded are treated as not
1089 // resolved, in order to fall back later.
1090 self.def_map.diagnostics.push(
1091 DefDiagnostic::unresolved_proc_macro(
1092 directive.module_id,
1093 loc.kind,
1094 ),
1095 );
1096
1097 let file_id = ast_id.ast_id.file_id;
1098 let item_tree = self.db.file_item_tree(file_id);
1099 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1100 self.skip_attrs
1101 .insert(InFile::new(file_id, *mod_item), attr.id);
1102 ModCollector {
1103 def_collector: &mut *self,
1104 macro_depth: directive.depth,
1105 module_id: directive.module_id,
1106 file_id,
1107 item_tree: &item_tree,
1108 mod_dir,
1109 }
1110 .collect(&[*mod_item]);
1111
1112 // Remove the macro directive.
1113 return false;
1114 }
1115 }
1116
1117 self.def_map.modules[directive.module_id]
1118 .scope
1119 .add_attr_macro_invoc(ast_id.ast_id, call_id);
1120
1121 resolved.push((directive.module_id, call_id, directive.depth));
1122 res = ReachedFixedPoint::No;
1123 return false;
1124 }
1125 Err(UnresolvedMacro { .. }) => (),
1126 }
1072 } 1127 }
1073 } 1128 }
1074 1129
@@ -1296,7 +1351,7 @@ impl ModCollector<'_, '_> {
1296 let imports = Import::from_use( 1351 let imports = Import::from_use(
1297 self.def_collector.db, 1352 self.def_collector.db,
1298 krate, 1353 krate,
1299 &self.item_tree, 1354 self.item_tree,
1300 ItemTreeId::new(self.file_id, import_id), 1355 ItemTreeId::new(self.file_id, import_id),
1301 ); 1356 );
1302 self.def_collector.unresolved_imports.extend(imports.into_iter().map( 1357 self.def_collector.unresolved_imports.extend(imports.into_iter().map(
@@ -1313,7 +1368,7 @@ impl ModCollector<'_, '_> {
1313 import: Import::from_extern_crate( 1368 import: Import::from_extern_crate(
1314 self.def_collector.db, 1369 self.def_collector.db,
1315 krate, 1370 krate,
1316 &self.item_tree, 1371 self.item_tree,
1317 ItemTreeId::new(self.file_id, import_id), 1372 ItemTreeId::new(self.file_id, import_id),
1318 ), 1373 ),
1319 status: PartialResolvedImport::Unresolved, 1374 status: PartialResolvedImport::Unresolved,
@@ -1628,7 +1683,7 @@ impl ModCollector<'_, '_> {
1628 self.def_collector.unresolved_macros.push(MacroDirective { 1683 self.def_collector.unresolved_macros.push(MacroDirective {
1629 module_id: self.module_id, 1684 module_id: self.module_id,
1630 depth: self.macro_depth + 1, 1685 depth: self.macro_depth + 1,
1631 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.id, mod_item }, 1686 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
1632 }); 1687 });
1633 1688
1634 return Err(()); 1689 return Err(());
@@ -1782,7 +1837,8 @@ impl ModCollector<'_, '_> {
1782 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); 1837 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1783 if attrs.by_key("rustc_builtin_macro").exists() { 1838 if attrs.by_key("rustc_builtin_macro").exists() {
1784 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1839 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1785 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); 1840 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
1841 .or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
1786 1842
1787 match macro_id { 1843 match macro_id {
1788 Some(macro_id) => { 1844 Some(macro_id) => {
@@ -1833,7 +1889,7 @@ impl ModCollector<'_, '_> {
1833 self.def_collector.def_map.with_ancestor_maps( 1889 self.def_collector.def_map.with_ancestor_maps(
1834 self.def_collector.db, 1890 self.def_collector.db,
1835 self.module_id, 1891 self.module_id,
1836 &mut |map, module| map[module].scope.get_legacy_macro(&name), 1892 &mut |map, module| map[module].scope.get_legacy_macro(name),
1837 ) 1893 )
1838 }) 1894 })
1839 }, 1895 },
@@ -1937,7 +1993,7 @@ mod tests {
1937 } 1993 }
1938 1994
1939 fn do_resolve(code: &str) -> DefMap { 1995 fn do_resolve(code: &str) -> DefMap {
1940 let (db, _file_id) = TestDB::with_single_file(&code); 1996 let (db, _file_id) = TestDB::with_single_file(code);
1941 let krate = db.test_crate(); 1997 let krate = db.test_crate();
1942 1998
1943 let edition = db.crate_graph()[krate].edition; 1999 let edition = db.crate_graph()[krate].edition;
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index c984148c3..629bc7952 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -93,7 +93,7 @@ impl DefMap {
93 let mut vis = match visibility { 93 let mut vis = match visibility {
94 RawVisibility::Module(path) => { 94 RawVisibility::Module(path) => {
95 let (result, remaining) = 95 let (result, remaining) =
96 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); 96 self.resolve_path(db, original_module, path, BuiltinShadowMode::Module);
97 if remaining.is_some() { 97 if remaining.is_some() {
98 return None; 98 return None;
99 } 99 }
@@ -205,7 +205,7 @@ impl DefMap {
205 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 205 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
206 }; 206 };
207 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 207 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
208 self.resolve_name_in_crate_root_or_extern_prelude(db, &segment) 208 self.resolve_name_in_crate_root_or_extern_prelude(db, segment)
209 } 209 }
210 PathKind::Plain => { 210 PathKind::Plain => {
211 let (_, segment) = match segments.next() { 211 let (_, segment) = match segments.next() {
@@ -222,7 +222,7 @@ impl DefMap {
222 if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module }; 222 if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
223 223
224 log::debug!("resolving {:?} in module", segment); 224 log::debug!("resolving {:?} in module", segment);
225 self.resolve_name_in_module(db, original_module, &segment, prefer_module) 225 self.resolve_name_in_module(db, original_module, segment, prefer_module)
226 } 226 }
227 PathKind::Super(lvl) => { 227 PathKind::Super(lvl) => {
228 let mut module = original_module; 228 let mut module = original_module;
@@ -269,7 +269,7 @@ impl DefMap {
269 Some((_, segment)) => segment, 269 Some((_, segment)) => segment,
270 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 270 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
271 }; 271 };
272 if let Some(def) = self.extern_prelude.get(&segment) { 272 if let Some(def) = self.extern_prelude.get(segment) {
273 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 273 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
274 PerNs::types(*def, Visibility::Public) 274 PerNs::types(*def, Visibility::Public)
275 } else { 275 } else {
@@ -319,13 +319,13 @@ impl DefMap {
319 }; 319 };
320 320
321 // Since it is a qualified path here, it should not contains legacy macros 321 // Since it is a qualified path here, it should not contains legacy macros
322 module_data.scope.get(&segment) 322 module_data.scope.get(segment)
323 } 323 }
324 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 324 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
325 // enum variant 325 // enum variant
326 cov_mark::hit!(can_import_enum_variant); 326 cov_mark::hit!(can_import_enum_variant);
327 let enum_data = db.enum_data(e); 327 let enum_data = db.enum_data(e);
328 match enum_data.variant(&segment) { 328 match enum_data.variant(segment) {
329 Some(local_id) => { 329 Some(local_id) => {
330 let variant = EnumVariantId { parent: e, local_id }; 330 let variant = EnumVariantId { parent: e, local_id };
331 match &*enum_data.variants[local_id].variant_data { 331 match &*enum_data.variants[local_id].variant_data {
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index 58c01354a..cf43f2a96 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -2,7 +2,6 @@ mod globs;
2mod incremental; 2mod incremental;
3mod macros; 3mod macros;
4mod mod_resolution; 4mod mod_resolution;
5mod diagnostics;
6mod primitives; 5mod primitives;
7 6
8use std::sync::Arc; 7use std::sync::Arc;
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
deleted file mode 100644
index ec6670952..000000000
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ /dev/null
@@ -1,229 +0,0 @@
1use base_db::fixture::WithFixture;
2
3use crate::test_db::TestDB;
4
5fn check_diagnostics(ra_fixture: &str) {
6 let db: TestDB = TestDB::with_files(ra_fixture);
7 db.check_diagnostics();
8}
9
10fn check_no_diagnostics(ra_fixture: &str) {
11 let db: TestDB = TestDB::with_files(ra_fixture);
12 db.check_no_diagnostics();
13}
14
15#[test]
16fn unresolved_import() {
17 check_diagnostics(
18 r"
19 use does_exist;
20 use does_not_exist;
21 //^^^^^^^^^^^^^^^^^^^ UnresolvedImport
22
23 mod does_exist {}
24 ",
25 );
26}
27
28#[test]
29fn unresolved_extern_crate() {
30 check_diagnostics(
31 r"
32 //- /main.rs crate:main deps:core
33 extern crate core;
34 extern crate doesnotexist;
35 //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate
36 //- /lib.rs crate:core
37 ",
38 );
39}
40
41#[test]
42fn extern_crate_self_as() {
43 cov_mark::check!(extern_crate_self_as);
44 check_diagnostics(
45 r"
46 //- /lib.rs
47 extern crate doesnotexist;
48 //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate
49 // Should not error.
50 extern crate self as foo;
51 struct Foo;
52 use foo::Foo as Bar;
53 ",
54 );
55}
56
57#[test]
58fn dedup_unresolved_import_from_unresolved_crate() {
59 check_diagnostics(
60 r"
61 //- /main.rs crate:main
62 mod a {
63 extern crate doesnotexist;
64 //^^^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedExternCrate
65
66 // Should not error, since we already errored for the missing crate.
67 use doesnotexist::{self, bla, *};
68
69 use crate::doesnotexist;
70 //^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedImport
71 }
72
73 mod m {
74 use super::doesnotexist;
75 //^^^^^^^^^^^^^^^^^^^^^^^^ UnresolvedImport
76 }
77 ",
78 );
79}
80
81#[test]
82fn unresolved_module() {
83 check_diagnostics(
84 r"
85 //- /lib.rs
86 mod foo;
87 mod bar;
88 //^^^^^^^^ UnresolvedModule
89 mod baz {}
90 //- /foo.rs
91 ",
92 );
93}
94
95#[test]
96fn inactive_item() {
97 // Additional tests in `cfg` crate. This only tests disabled cfgs.
98
99 check_diagnostics(
100 r#"
101 //- /lib.rs
102 #[cfg(no)] pub fn f() {}
103 //^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
104
105 #[cfg(no)] #[cfg(no2)] mod m;
106 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
107
108 #[cfg(all(not(a), b))] enum E {}
109 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
110
111 #[cfg(feature = "std")] use std;
112 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
113 "#,
114 );
115}
116
117/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
118#[test]
119fn inactive_via_cfg_attr() {
120 cov_mark::check!(cfg_attr_active);
121 check_diagnostics(
122 r#"
123 //- /lib.rs
124 #[cfg_attr(not(never), cfg(no))] fn f() {}
125 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
126
127 #[cfg_attr(not(never), cfg(not(no)))] fn f() {}
128
129 #[cfg_attr(never, cfg(no))] fn g() {}
130
131 #[cfg_attr(not(never), inline, cfg(no))] fn h() {}
132 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnconfiguredCode
133 "#,
134 );
135}
136
137#[test]
138fn unresolved_legacy_scope_macro() {
139 check_diagnostics(
140 r#"
141 //- /lib.rs
142 macro_rules! m { () => {} }
143
144 m!();
145 m2!();
146 //^^^^^^ UnresolvedMacroCall
147 "#,
148 );
149}
150
151#[test]
152fn unresolved_module_scope_macro() {
153 check_diagnostics(
154 r#"
155 //- /lib.rs
156 mod mac {
157 #[macro_export]
158 macro_rules! m { () => {} }
159 }
160
161 self::m!();
162 self::m2!();
163 //^^^^^^^^^^^^ UnresolvedMacroCall
164 "#,
165 );
166}
167
168#[test]
169fn builtin_macro_fails_expansion() {
170 check_diagnostics(
171 r#"
172 //- /lib.rs
173 #[rustc_builtin_macro]
174 macro_rules! include { () => {} }
175
176 include!("doesntexist");
177 //^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `doesntexist`
178 "#,
179 );
180}
181
182#[test]
183fn include_macro_should_allow_empty_content() {
184 check_no_diagnostics(
185 r#"
186 //- /lib.rs
187 #[rustc_builtin_macro]
188 macro_rules! include { () => {} }
189
190 include!("bar.rs");
191 //- /bar.rs
192 // empty
193 "#,
194 );
195}
196
197#[test]
198fn good_out_dir_diagnostic() {
199 check_diagnostics(
200 r#"
201 #[rustc_builtin_macro]
202 macro_rules! include { () => {} }
203 #[rustc_builtin_macro]
204 macro_rules! env { () => {} }
205 #[rustc_builtin_macro]
206 macro_rules! concat { () => {} }
207
208 include!(concat!(env!("OUT_DIR"), "/out.rs"));
209 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
210 "#,
211 );
212}
213
214#[test]
215fn register_attr_and_tool() {
216 cov_mark::check!(register_attr);
217 cov_mark::check!(register_tool);
218 check_no_diagnostics(
219 r#"
220#![register_tool(tool)]
221#![register_attr(attr)]
222
223#[tool::path]
224#[attr]
225struct S;
226 "#,
227 );
228 // NB: we don't currently emit diagnostics here
229}