aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-05-19 22:35:09 +0100
committerJonas Schievink <[email protected]>2021-05-19 22:35:09 +0100
commitd4eb6708d9d62e951e6b594eb4481e944daa8bc3 (patch)
treefdb5a37e1cb811000e381aeacfe593edb193a0e9 /crates/hir_def
parent7cb5920372017b81b954705c03d0b24e60c3e223 (diff)
Track in-scope derive helpers during nameres
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/nameres/collector.rs34
1 files changed, 26 insertions, 8 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 02ceb8d50..3896be25d 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -43,7 +43,7 @@ use crate::{
43 UnresolvedMacro, 43 UnresolvedMacro,
44}; 44};
45 45
46use super::proc_macro::ProcMacroDef; 46use super::proc_macro::{ProcMacroDef, ProcMacroKind};
47 47
48const GLOB_RECURSION_LIMIT: usize = 100; 48const GLOB_RECURSION_LIMIT: usize = 100;
49const EXPANSION_DEPTH_LIMIT: usize = 128; 49const EXPANSION_DEPTH_LIMIT: usize = 128;
@@ -101,6 +101,7 @@ pub(super) fn collect_defs(
101 exports_proc_macros: false, 101 exports_proc_macros: false,
102 from_glob_import: Default::default(), 102 from_glob_import: Default::default(),
103 ignore_attrs_on: FxHashSet::default(), 103 ignore_attrs_on: FxHashSet::default(),
104 derive_helpers_in_scope: FxHashMap::default(),
104 }; 105 };
105 match block { 106 match block {
106 Some(block) => { 107 Some(block) => {
@@ -247,6 +248,9 @@ struct DefCollector<'a> {
247 exports_proc_macros: bool, 248 exports_proc_macros: bool,
248 from_glob_import: PerNsGlobImports, 249 from_glob_import: PerNsGlobImports,
249 ignore_attrs_on: FxHashSet<InFile<ModItem>>, 250 ignore_attrs_on: FxHashSet<InFile<ModItem>>,
251 /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
252 /// attributes.
253 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
250} 254}
251 255
252impl DefCollector<'_> { 256impl DefCollector<'_> {
@@ -950,21 +954,35 @@ impl DefCollector<'_> {
950 // First, fetch the raw expansion result for purposes of error reporting. This goes through 954 // First, fetch the raw expansion result for purposes of error reporting. This goes through
951 // `macro_expand_error` to avoid depending on the full expansion result (to improve 955 // `macro_expand_error` to avoid depending on the full expansion result (to improve
952 // incrementality). 956 // incrementality).
957 let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
953 let err = self.db.macro_expand_error(macro_call_id); 958 let err = self.db.macro_expand_error(macro_call_id);
954 if let Some(err) = err { 959 if let Some(err) = err {
955 let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
956
957 let diag = match err { 960 let diag = match err {
958 hir_expand::ExpandError::UnresolvedProcMacro => { 961 hir_expand::ExpandError::UnresolvedProcMacro => {
959 // Missing proc macros are non-fatal, so they are handled specially. 962 // Missing proc macros are non-fatal, so they are handled specially.
960 DefDiagnostic::unresolved_proc_macro(module_id, loc.kind) 963 DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
961 } 964 }
962 _ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()), 965 _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
963 }; 966 };
964 967
965 self.def_map.diagnostics.push(diag); 968 self.def_map.diagnostics.push(diag);
966 } 969 }
967 970
971 // If we've just resolved a derive, record its helper attributes.
972 if let MacroCallKind::Derive { ast_id, .. } = &loc.kind {
973 if loc.def.krate != self.def_map.krate {
974 let def_map = self.db.crate_def_map(loc.def.krate);
975 if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
976 if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
977 self.derive_helpers_in_scope
978 .entry(*ast_id)
979 .or_default()
980 .extend(helpers.iter().cloned());
981 }
982 }
983 }
984 }
985
968 // Then, fetch and process the item tree. This will reuse the expansion result from above. 986 // Then, fetch and process the item tree. This will reuse the expansion result from above.
969 let item_tree = self.db.file_item_tree(file_id); 987 let item_tree = self.db.file_item_tree(file_id);
970 let mod_dir = self.mod_dirs[&module_id].clone(); 988 let mod_dir = self.mod_dirs[&module_id].clone();
@@ -1120,9 +1138,8 @@ impl ModCollector<'_, '_> {
1120 } 1138 }
1121 1139
1122 if let Err(()) = self.resolve_attributes(&attrs, item) { 1140 if let Err(()) = self.resolve_attributes(&attrs, item) {
1123 // Do not process the item. It has at least one non-builtin attribute, which *must* 1141 // Do not process the item. It has at least one non-builtin attribute, so the
1124 // resolve to a proc macro (or fail to resolve), so we'll never see this item during 1142 // fixed-point algorithm is required to resolve the rest of them.
1125 // normal name resolution.
1126 continue; 1143 continue;
1127 } 1144 }
1128 1145
@@ -1721,6 +1738,7 @@ mod tests {
1721 exports_proc_macros: false, 1738 exports_proc_macros: false,
1722 from_glob_import: Default::default(), 1739 from_glob_import: Default::default(),
1723 ignore_attrs_on: FxHashSet::default(), 1740 ignore_attrs_on: FxHashSet::default(),
1741 derive_helpers_in_scope: FxHashMap::default(),
1724 }; 1742 };
1725 collector.seed_with_top_level(); 1743 collector.seed_with_top_level();
1726 collector.collect(); 1744 collector.collect();