diff options
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 136 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 59 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 26 |
3 files changed, 147 insertions, 74 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d58135ec9..05ceb1efb 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 16 | AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -23,6 +23,7 @@ use crate::{ | |||
23 | attr::Attrs, | 23 | attr::Attrs, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | ||
26 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 28 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
@@ -54,20 +55,22 @@ pub(super) fn collect_defs( | |||
54 | ) -> DefMap { | 55 | ) -> DefMap { |
55 | let crate_graph = db.crate_graph(); | 56 | let crate_graph = db.crate_graph(); |
56 | 57 | ||
57 | // populate external prelude | 58 | if block.is_none() { |
58 | for dep in &crate_graph[def_map.krate].dependencies { | 59 | // populate external prelude |
59 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); | 60 | for dep in &crate_graph[def_map.krate].dependencies { |
60 | let dep_def_map = db.crate_def_map(dep.crate_id); | 61 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); |
61 | def_map | 62 | let dep_def_map = db.crate_def_map(dep.crate_id); |
62 | .extern_prelude | 63 | def_map |
63 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); | 64 | .extern_prelude |
64 | 65 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); | |
65 | // look for the prelude | 66 | |
66 | // If the dependency defines a prelude, we overwrite an already defined | 67 | // look for the prelude |
67 | // prelude. This is necessary to import the "std" prelude if a crate | 68 | // If the dependency defines a prelude, we overwrite an already defined |
68 | // depends on both "core" and "std". | 69 | // prelude. This is necessary to import the "std" prelude if a crate |
69 | if dep_def_map.prelude.is_some() { | 70 | // depends on both "core" and "std". |
70 | def_map.prelude = dep_def_map.prelude; | 71 | if dep_def_map.prelude.is_some() { |
72 | def_map.prelude = dep_def_map.prelude; | ||
73 | } | ||
71 | } | 74 | } |
72 | } | 75 | } |
73 | 76 | ||
@@ -106,7 +109,9 @@ pub(super) fn collect_defs( | |||
106 | } | 109 | } |
107 | } | 110 | } |
108 | collector.collect(); | 111 | collector.collect(); |
109 | collector.finish() | 112 | let mut def_map = collector.finish(); |
113 | def_map.shrink_to_fit(); | ||
114 | def_map | ||
110 | } | 115 | } |
111 | 116 | ||
112 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 117 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
@@ -137,7 +142,7 @@ enum ImportSource { | |||
137 | 142 | ||
138 | #[derive(Clone, Debug, Eq, PartialEq)] | 143 | #[derive(Clone, Debug, Eq, PartialEq)] |
139 | struct Import { | 144 | struct Import { |
140 | path: ModPath, | 145 | path: Interned<ModPath>, |
141 | alias: Option<ImportAlias>, | 146 | alias: Option<ImportAlias>, |
142 | visibility: RawVisibility, | 147 | visibility: RawVisibility, |
143 | is_glob: bool, | 148 | is_glob: bool, |
@@ -179,7 +184,10 @@ impl Import { | |||
179 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | 184 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); |
180 | let visibility = &tree[it.visibility]; | 185 | let visibility = &tree[it.visibility]; |
181 | Self { | 186 | Self { |
182 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 187 | path: Interned::new(ModPath::from_segments( |
188 | PathKind::Plain, | ||
189 | iter::once(it.name.clone()), | ||
190 | )), | ||
183 | alias: it.alias.clone(), | 191 | alias: it.alias.clone(), |
184 | visibility: visibility.clone(), | 192 | visibility: visibility.clone(), |
185 | is_glob: false, | 193 | is_glob: false, |
@@ -207,8 +215,8 @@ struct MacroDirective { | |||
207 | 215 | ||
208 | #[derive(Clone, Debug, Eq, PartialEq)] | 216 | #[derive(Clone, Debug, Eq, PartialEq)] |
209 | enum MacroDirectiveKind { | 217 | enum MacroDirectiveKind { |
210 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, legacy: Option<MacroCallId> }, | 218 | FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, |
211 | Derive { ast_id: AstIdWithPath<ast::Item> }, | 219 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, |
212 | } | 220 | } |
213 | 221 | ||
214 | struct DefData<'a> { | 222 | struct DefData<'a> { |
@@ -470,7 +478,7 @@ impl DefCollector<'_> { | |||
470 | self.def_map.edition, | 478 | self.def_map.edition, |
471 | ); | 479 | ); |
472 | 480 | ||
473 | let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); | 481 | let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name); |
474 | 482 | ||
475 | if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { | 483 | if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { |
476 | cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); | 484 | cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); |
@@ -526,6 +534,7 @@ impl DefCollector<'_> { | |||
526 | log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); | 534 | log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); |
527 | if import.is_extern_crate { | 535 | if import.is_extern_crate { |
528 | let res = self.def_map.resolve_name_in_extern_prelude( | 536 | let res = self.def_map.resolve_name_in_extern_prelude( |
537 | self.db, | ||
529 | &import | 538 | &import |
530 | .path | 539 | .path |
531 | .as_ident() | 540 | .as_ident() |
@@ -798,13 +807,7 @@ impl DefCollector<'_> { | |||
798 | let mut res = ReachedFixedPoint::Yes; | 807 | let mut res = ReachedFixedPoint::Yes; |
799 | macros.retain(|directive| { | 808 | macros.retain(|directive| { |
800 | match &directive.kind { | 809 | match &directive.kind { |
801 | MacroDirectiveKind::FnLike { ast_id, legacy } => { | 810 | MacroDirectiveKind::FnLike { ast_id } => { |
802 | if let Some(call_id) = legacy { | ||
803 | res = ReachedFixedPoint::No; | ||
804 | resolved.push((directive.module_id, *call_id, directive.depth)); | ||
805 | return false; | ||
806 | } | ||
807 | |||
808 | match macro_call_as_call_id( | 811 | match macro_call_as_call_id( |
809 | ast_id, | 812 | ast_id, |
810 | self.db, | 813 | self.db, |
@@ -826,19 +829,23 @@ impl DefCollector<'_> { | |||
826 | res = ReachedFixedPoint::No; | 829 | res = ReachedFixedPoint::No; |
827 | return false; | 830 | return false; |
828 | } | 831 | } |
829 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | 832 | Err(UnresolvedMacro { .. }) | Ok(Err(_)) => {} |
830 | } | 833 | } |
831 | } | 834 | } |
832 | MacroDirectiveKind::Derive { ast_id } => { | 835 | MacroDirectiveKind::Derive { ast_id, derive_attr } => { |
833 | match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { | 836 | match derive_macro_as_call_id( |
834 | self.resolve_derive_macro(directive.module_id, &path) | 837 | ast_id, |
835 | }) { | 838 | *derive_attr, |
839 | self.db, | ||
840 | self.def_map.krate, | ||
841 | |path| self.resolve_derive_macro(directive.module_id, &path), | ||
842 | ) { | ||
836 | Ok(call_id) => { | 843 | Ok(call_id) => { |
837 | resolved.push((directive.module_id, call_id, 0)); | 844 | resolved.push((directive.module_id, call_id, directive.depth)); |
838 | res = ReachedFixedPoint::No; | 845 | res = ReachedFixedPoint::No; |
839 | return false; | 846 | return false; |
840 | } | 847 | } |
841 | Err(UnresolvedMacro) => (), | 848 | Err(UnresolvedMacro { .. }) => (), |
842 | } | 849 | } |
843 | } | 850 | } |
844 | } | 851 | } |
@@ -936,10 +943,11 @@ impl DefCollector<'_> { | |||
936 | &mut |_| (), | 943 | &mut |_| (), |
937 | ) { | 944 | ) { |
938 | Ok(_) => (), | 945 | Ok(_) => (), |
939 | Err(UnresolvedMacro) => { | 946 | Err(UnresolvedMacro { path }) => { |
940 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( | 947 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( |
941 | directive.module_id, | 948 | directive.module_id, |
942 | ast_id.ast_id, | 949 | ast_id.ast_id, |
950 | path, | ||
943 | )); | 951 | )); |
944 | } | 952 | } |
945 | }, | 953 | }, |
@@ -1161,19 +1169,27 @@ impl ModCollector<'_, '_> { | |||
1161 | } | 1169 | } |
1162 | ModItem::Const(id) => { | 1170 | ModItem::Const(id) => { |
1163 | let it = &self.item_tree[id]; | 1171 | let it = &self.item_tree[id]; |
1164 | 1172 | let const_id = ConstLoc { | |
1165 | if let Some(name) = &it.name { | 1173 | container: module.into(), |
1166 | def = Some(DefData { | 1174 | id: ItemTreeId::new(self.file_id, id), |
1167 | id: ConstLoc { | 1175 | } |
1168 | container: module.into(), | 1176 | .intern(self.def_collector.db); |
1169 | id: ItemTreeId::new(self.file_id, id), | 1177 | |
1170 | } | 1178 | match &it.name { |
1171 | .intern(self.def_collector.db) | 1179 | Some(name) => { |
1172 | .into(), | 1180 | def = Some(DefData { |
1173 | name, | 1181 | id: const_id.into(), |
1174 | visibility: &self.item_tree[it.visibility], | 1182 | name, |
1175 | has_constructor: false, | 1183 | visibility: &self.item_tree[it.visibility], |
1176 | }); | 1184 | has_constructor: false, |
1185 | }); | ||
1186 | } | ||
1187 | None => { | ||
1188 | // const _: T = ...; | ||
1189 | self.def_collector.def_map.modules[self.module_id] | ||
1190 | .scope | ||
1191 | .define_unnamed_const(const_id); | ||
1192 | } | ||
1177 | } | 1193 | } |
1178 | } | 1194 | } |
1179 | ModItem::Static(id) => { | 1195 | ModItem::Static(id) => { |
@@ -1358,7 +1374,7 @@ impl ModCollector<'_, '_> { | |||
1358 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1374 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1359 | module_id: self.module_id, | 1375 | module_id: self.module_id, |
1360 | depth: self.macro_depth + 1, | 1376 | depth: self.macro_depth + 1, |
1361 | kind: MacroDirectiveKind::Derive { ast_id }, | 1377 | kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id }, |
1362 | }); | 1378 | }); |
1363 | } | 1379 | } |
1364 | } | 1380 | } |
@@ -1400,8 +1416,18 @@ impl ModCollector<'_, '_> { | |||
1400 | 1416 | ||
1401 | // Case 1: builtin macros | 1417 | // Case 1: builtin macros |
1402 | if attrs.by_key("rustc_builtin_macro").exists() { | 1418 | if attrs.by_key("rustc_builtin_macro").exists() { |
1419 | // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name. | ||
1420 | let name; | ||
1421 | let name = match attrs.by_key("rustc_builtin_macro").string_value() { | ||
1422 | Some(it) => { | ||
1423 | // FIXME: a hacky way to create a Name from string. | ||
1424 | name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name(); | ||
1425 | &name | ||
1426 | } | ||
1427 | None => &mac.name, | ||
1428 | }; | ||
1403 | let krate = self.def_collector.def_map.krate; | 1429 | let krate = self.def_collector.def_map.krate; |
1404 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1430 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { |
1405 | self.def_collector.define_macro_rules( | 1431 | self.def_collector.define_macro_rules( |
1406 | self.module_id, | 1432 | self.module_id, |
1407 | mac.name.clone(), | 1433 | mac.name.clone(), |
@@ -1464,7 +1490,7 @@ impl ModCollector<'_, '_> { | |||
1464 | } | 1490 | } |
1465 | 1491 | ||
1466 | fn collect_macro_call(&mut self, mac: &MacroCall) { | 1492 | fn collect_macro_call(&mut self, mac: &MacroCall) { |
1467 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1493 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone()); |
1468 | 1494 | ||
1469 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1495 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1470 | let mut error = None; | 1496 | let mut error = None; |
@@ -1500,12 +1526,12 @@ impl ModCollector<'_, '_> { | |||
1500 | // Built-in macro failed eager expansion. | 1526 | // Built-in macro failed eager expansion. |
1501 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( | 1527 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( |
1502 | self.module_id, | 1528 | self.module_id, |
1503 | MacroCallKind::FnLike(ast_id.ast_id), | 1529 | MacroCallKind::FnLike { ast_id: ast_id.ast_id }, |
1504 | error.unwrap().to_string(), | 1530 | error.unwrap().to_string(), |
1505 | )); | 1531 | )); |
1506 | return; | 1532 | return; |
1507 | } | 1533 | } |
1508 | Err(UnresolvedMacro) => (), | 1534 | Err(UnresolvedMacro { .. }) => (), |
1509 | } | 1535 | } |
1510 | 1536 | ||
1511 | // Case 2: resolve in module scope, expand during name resolution. | 1537 | // Case 2: resolve in module scope, expand during name resolution. |
@@ -1517,7 +1543,7 @@ impl ModCollector<'_, '_> { | |||
1517 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1543 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1518 | module_id: self.module_id, | 1544 | module_id: self.module_id, |
1519 | depth: self.macro_depth + 1, | 1545 | depth: self.macro_depth + 1, |
1520 | kind: MacroDirectiveKind::FnLike { ast_id, legacy: None }, | 1546 | kind: MacroDirectiveKind::FnLike { ast_id }, |
1521 | }); | 1547 | }); |
1522 | } | 1548 | } |
1523 | 1549 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 60471937c..c984148c3 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -60,12 +60,26 @@ impl ResolvePathResult { | |||
60 | } | 60 | } |
61 | 61 | ||
62 | impl DefMap { | 62 | impl DefMap { |
63 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { | 63 | pub(super) fn resolve_name_in_extern_prelude( |
64 | &self, | ||
65 | db: &dyn DefDatabase, | ||
66 | name: &Name, | ||
67 | ) -> PerNs { | ||
64 | if name == &name!(self) { | 68 | if name == &name!(self) { |
65 | cov_mark::hit!(extern_crate_self_as); | 69 | cov_mark::hit!(extern_crate_self_as); |
66 | return PerNs::types(self.module_id(self.root).into(), Visibility::Public); | 70 | return PerNs::types(self.module_id(self.root).into(), Visibility::Public); |
67 | } | 71 | } |
68 | self.extern_prelude | 72 | |
73 | let arc; | ||
74 | let root = match self.block { | ||
75 | Some(_) => { | ||
76 | arc = self.crate_root(db).def_map(db); | ||
77 | &*arc | ||
78 | } | ||
79 | None => self, | ||
80 | }; | ||
81 | |||
82 | root.extern_prelude | ||
69 | .get(name) | 83 | .get(name) |
70 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) | 84 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) |
71 | } | 85 | } |
@@ -191,7 +205,7 @@ impl DefMap { | |||
191 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 205 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
192 | }; | 206 | }; |
193 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); | 207 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); |
194 | self.resolve_name_in_crate_root_or_extern_prelude(&segment) | 208 | self.resolve_name_in_crate_root_or_extern_prelude(db, &segment) |
195 | } | 209 | } |
196 | PathKind::Plain => { | 210 | PathKind::Plain => { |
197 | let (_, segment) = match segments.next() { | 211 | let (_, segment) = match segments.next() { |
@@ -373,7 +387,13 @@ impl DefMap { | |||
373 | .get_legacy_macro(name) | 387 | .get_legacy_macro(name) |
374 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); | 388 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); |
375 | let from_scope = self[module].scope.get(name); | 389 | let from_scope = self[module].scope.get(name); |
376 | let from_builtin = BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none); | 390 | let from_builtin = match self.block { |
391 | Some(_) => { | ||
392 | // Only resolve to builtins in the root `DefMap`. | ||
393 | PerNs::none() | ||
394 | } | ||
395 | None => BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none), | ||
396 | }; | ||
377 | let from_scope_or_builtin = match shadow { | 397 | let from_scope_or_builtin = match shadow { |
378 | BuiltinShadowMode::Module => from_scope.or(from_builtin), | 398 | BuiltinShadowMode::Module => from_scope.or(from_builtin), |
379 | BuiltinShadowMode::Other => { | 399 | BuiltinShadowMode::Other => { |
@@ -384,24 +404,31 @@ impl DefMap { | |||
384 | } | 404 | } |
385 | } | 405 | } |
386 | }; | 406 | }; |
387 | // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude | 407 | let from_extern_prelude = self |
388 | // from the crate DefMap. | 408 | .extern_prelude |
389 | let from_extern_prelude = match self.block { | 409 | .get(name) |
390 | Some(_) => PerNs::none(), | 410 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); |
391 | None => self | ||
392 | .extern_prelude | ||
393 | .get(name) | ||
394 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)), | ||
395 | }; | ||
396 | 411 | ||
397 | let from_prelude = self.resolve_in_prelude(db, name); | 412 | let from_prelude = self.resolve_in_prelude(db, name); |
398 | 413 | ||
399 | from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) | 414 | from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) |
400 | } | 415 | } |
401 | 416 | ||
402 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { | 417 | fn resolve_name_in_crate_root_or_extern_prelude( |
403 | let from_crate_root = self[self.root].scope.get(name); | 418 | &self, |
404 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | 419 | db: &dyn DefDatabase, |
420 | name: &Name, | ||
421 | ) -> PerNs { | ||
422 | let arc; | ||
423 | let crate_def_map = match self.block { | ||
424 | Some(_) => { | ||
425 | arc = self.crate_root(db).def_map(db); | ||
426 | &arc | ||
427 | } | ||
428 | None => self, | ||
429 | }; | ||
430 | let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name); | ||
431 | let from_extern_prelude = self.resolve_name_in_extern_prelude(db, name); | ||
405 | 432 | ||
406 | from_crate_root.or(from_extern_prelude) | 433 | from_crate_root.or(from_extern_prelude) |
407 | } | 434 | } |
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs index a89061c2e..543975e07 100644 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ b/crates/hir_def/src/nameres/tests/diagnostics.rs | |||
@@ -7,6 +7,11 @@ fn check_diagnostics(ra_fixture: &str) { | |||
7 | db.check_diagnostics(); | 7 | db.check_diagnostics(); |
8 | } | 8 | } |
9 | 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 | |||
10 | #[test] | 15 | #[test] |
11 | fn unresolved_import() { | 16 | fn unresolved_import() { |
12 | check_diagnostics( | 17 | check_diagnostics( |
@@ -165,7 +170,7 @@ fn unresolved_legacy_scope_macro() { | |||
165 | 170 | ||
166 | m!(); | 171 | m!(); |
167 | m2!(); | 172 | m2!(); |
168 | //^^^^^^ unresolved macro call | 173 | //^^^^^^ unresolved macro `self::m2!` |
169 | "#, | 174 | "#, |
170 | ); | 175 | ); |
171 | } | 176 | } |
@@ -182,7 +187,7 @@ fn unresolved_module_scope_macro() { | |||
182 | 187 | ||
183 | self::m!(); | 188 | self::m!(); |
184 | self::m2!(); | 189 | self::m2!(); |
185 | //^^^^^^^^^^^^ unresolved macro call | 190 | //^^^^^^^^^^^^ unresolved macro `self::m2!` |
186 | "#, | 191 | "#, |
187 | ); | 192 | ); |
188 | } | 193 | } |
@@ -202,6 +207,21 @@ fn builtin_macro_fails_expansion() { | |||
202 | } | 207 | } |
203 | 208 | ||
204 | #[test] | 209 | #[test] |
210 | fn include_macro_should_allow_empty_content() { | ||
211 | check_no_diagnostics( | ||
212 | r#" | ||
213 | //- /lib.rs | ||
214 | #[rustc_builtin_macro] | ||
215 | macro_rules! include { () => {} } | ||
216 | |||
217 | include!("bar.rs"); | ||
218 | //- /bar.rs | ||
219 | // empty | ||
220 | "#, | ||
221 | ); | ||
222 | } | ||
223 | |||
224 | #[test] | ||
205 | fn good_out_dir_diagnostic() { | 225 | fn good_out_dir_diagnostic() { |
206 | check_diagnostics( | 226 | check_diagnostics( |
207 | r#" | 227 | r#" |
@@ -213,7 +233,7 @@ fn good_out_dir_diagnostic() { | |||
213 | macro_rules! concat { () => {} } | 233 | macro_rules! concat { () => {} } |
214 | 234 | ||
215 | include!(concat!(env!("OUT_DIR"), "/out.rs")); | 235 | include!(concat!(env!("OUT_DIR"), "/out.rs")); |
216 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix | 236 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix |
217 | "#, | 237 | "#, |
218 | ); | 238 | ); |
219 | } | 239 | } |