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.rs49
-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, 37 insertions, 254 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 93f30f23d..fc2c50fb8 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -500,7 +500,7 @@ impl DefCollector<'_> {
500 let (per_ns, _) = self.def_map.resolve_path( 500 let (per_ns, _) = self.def_map.resolve_path(
501 self.db, 501 self.db,
502 self.def_map.root, 502 self.def_map.root,
503 &path, 503 path,
504 BuiltinShadowMode::Other, 504 BuiltinShadowMode::Other,
505 ); 505 );
506 506
@@ -722,7 +722,7 @@ impl DefCollector<'_> {
722 if import.is_extern_crate { 722 if import.is_extern_crate {
723 let res = self.def_map.resolve_name_in_extern_prelude( 723 let res = self.def_map.resolve_name_in_extern_prelude(
724 self.db, 724 self.db,
725 &import 725 import
726 .path 726 .path
727 .as_ident() 727 .as_ident()
728 .expect("extern crate should have been desugared to one-element path"), 728 .expect("extern crate should have been desugared to one-element path"),
@@ -1351,7 +1351,7 @@ impl ModCollector<'_, '_> {
1351 let imports = Import::from_use( 1351 let imports = Import::from_use(
1352 self.def_collector.db, 1352 self.def_collector.db,
1353 krate, 1353 krate,
1354 &self.item_tree, 1354 self.item_tree,
1355 ItemTreeId::new(self.file_id, import_id), 1355 ItemTreeId::new(self.file_id, import_id),
1356 ); 1356 );
1357 self.def_collector.unresolved_imports.extend(imports.into_iter().map( 1357 self.def_collector.unresolved_imports.extend(imports.into_iter().map(
@@ -1368,7 +1368,7 @@ impl ModCollector<'_, '_> {
1368 import: Import::from_extern_crate( 1368 import: Import::from_extern_crate(
1369 self.def_collector.db, 1369 self.def_collector.db,
1370 krate, 1370 krate,
1371 &self.item_tree, 1371 self.item_tree,
1372 ItemTreeId::new(self.file_id, import_id), 1372 ItemTreeId::new(self.file_id, import_id),
1373 ), 1373 ),
1374 status: PartialResolvedImport::Unresolved, 1374 status: PartialResolvedImport::Unresolved,
@@ -1889,7 +1889,7 @@ impl ModCollector<'_, '_> {
1889 self.def_collector.def_map.with_ancestor_maps( 1889 self.def_collector.def_map.with_ancestor_maps(
1890 self.def_collector.db, 1890 self.def_collector.db,
1891 self.module_id, 1891 self.module_id,
1892 &mut |map, module| map[module].scope.get_legacy_macro(&name), 1892 &mut |map, module| map[module].scope.get_legacy_macro(name),
1893 ) 1893 )
1894 }) 1894 })
1895 }, 1895 },
@@ -1992,8 +1992,8 @@ mod tests {
1992 collector.def_map 1992 collector.def_map
1993 } 1993 }
1994 1994
1995 fn do_resolve(code: &str) -> DefMap { 1995 fn do_resolve(not_ra_fixture: &str) -> DefMap {
1996 let (db, _file_id) = TestDB::with_single_file(&code); 1996 let (db, _file_id) = TestDB::with_single_file(not_ra_fixture);
1997 let krate = db.test_crate(); 1997 let krate = db.test_crate();
1998 1998
1999 let edition = db.crate_graph()[krate].edition; 1999 let edition = db.crate_graph()[krate].edition;
@@ -2005,24 +2005,37 @@ mod tests {
2005 fn test_macro_expand_will_stop_1() { 2005 fn test_macro_expand_will_stop_1() {
2006 do_resolve( 2006 do_resolve(
2007 r#" 2007 r#"
2008 macro_rules! foo { 2008macro_rules! foo {
2009 ($($ty:ty)*) => { foo!($($ty)*); } 2009 ($($ty:ty)*) => { foo!($($ty)*); }
2010 } 2010}
2011 foo!(KABOOM); 2011foo!(KABOOM);
2012 "#, 2012"#,
2013 );
2014 do_resolve(
2015 r#"
2016macro_rules! foo {
2017 ($($ty:ty)*) => { foo!(() $($ty)*); }
2018}
2019foo!(KABOOM);
2020"#,
2013 ); 2021 );
2014 } 2022 }
2015 2023
2016 #[ignore] // this test does succeed, but takes quite a while :/ 2024 #[ignore]
2017 #[test] 2025 #[test]
2018 fn test_macro_expand_will_stop_2() { 2026 fn test_macro_expand_will_stop_2() {
2027 // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2028 // the release mode. That's why the argument is not an ra_fixture --
2029 // otherwise injection highlighting gets stuck.
2030 //
2031 // We need to find a way to fail this faster.
2019 do_resolve( 2032 do_resolve(
2020 r#" 2033 r#"
2021 macro_rules! foo { 2034macro_rules! foo {
2022 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); } 2035 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2023 } 2036}
2024 foo!(KABOOM); 2037foo!(KABOOM);
2025 "#, 2038"#,
2026 ); 2039 );
2027 } 2040 }
2028} 2041}
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}