diff options
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 82 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 229 |
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}; | |||
9 | use cfg::{CfgExpr, CfgOptions}; | 9 | use cfg::{CfgExpr, CfgOptions}; |
10 | use hir_expand::{ | 10 | use 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 | ||
24 | use crate::{ | 25 | use 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 { | |||
223 | enum MacroDirectiveKind { | 224 | enum 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 | ||
229 | struct DefData<'a> { | 230 | struct 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; | |||
2 | mod incremental; | 2 | mod incremental; |
3 | mod macros; | 3 | mod macros; |
4 | mod mod_resolution; | 4 | mod mod_resolution; |
5 | mod diagnostics; | ||
6 | mod primitives; | 5 | mod primitives; |
7 | 6 | ||
8 | use std::sync::Arc; | 7 | use 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 @@ | |||
1 | use base_db::fixture::WithFixture; | ||
2 | |||
3 | use crate::test_db::TestDB; | ||
4 | |||
5 | fn check_diagnostics(ra_fixture: &str) { | ||
6 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
7 | db.check_diagnostics(); | ||
8 | } | ||
9 | |||
10 | fn check_no_diagnostics(ra_fixture: &str) { | ||
11 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
12 | db.check_no_diagnostics(); | ||
13 | } | ||
14 | |||
15 | #[test] | ||
16 | fn 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] | ||
29 | fn 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] | ||
42 | fn 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] | ||
58 | fn 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] | ||
82 | fn 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] | ||
96 | fn 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] | ||
119 | fn 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] | ||
138 | fn 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] | ||
152 | fn 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] | ||
169 | fn 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] | ||
183 | fn 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] | ||
198 | fn 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] | ||
215 | fn 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] | ||
225 | struct S; | ||
226 | "#, | ||
227 | ); | ||
228 | // NB: we don't currently emit diagnostics here | ||
229 | } | ||