Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
| -rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 219 |
1 files changed, 101 insertions, 118 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index e45711db75..bafba0672f 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -9,7 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId}; use cfg::{CfgExpr, CfgOptions}; use hir_expand::{ ast_id_map::FileAstId, - builtin_attr_macro::{find_builtin_attr, is_builtin_test_or_bench_attr}, + builtin_attr_macro::find_builtin_attr, builtin_derive_macro::find_builtin_derive, builtin_fn_macro::find_builtin_macro, name::{name, AsName, Name}, @@ -781,7 +781,7 @@ impl DefCollector<'_> { } fn resolve_extern_crate(&self, name: &Name) -> PerNs { - if name == &name!(self) { + if *name == name!(self) { cov_mark::hit!(extern_crate_self_as); let root = match self.def_map.block { Some(_) => { @@ -1054,14 +1054,15 @@ impl DefCollector<'_> { match &directive.kind { MacroDirectiveKind::FnLike { ast_id, expand_to } => { - match macro_call_as_call_id( + let call_id = macro_call_as_call_id( ast_id, *expand_to, self.db, self.def_map.krate, &resolver, &mut |_err| (), - ) { + ); + match call_id { Ok(Ok(call_id)) => { resolved.push((directive.module_id, call_id, directive.depth)); res = ReachedFixedPoint::No; @@ -1071,13 +1072,14 @@ impl DefCollector<'_> { } } MacroDirectiveKind::Derive { ast_id, derive_attr } => { - match derive_macro_as_call_id( + let call_id = derive_macro_as_call_id( ast_id, *derive_attr, self.db, self.def_map.krate, &resolver, - ) { + ); + match call_id { Ok(call_id) => { self.def_map.modules[directive.module_id].scope.add_derive_macro_invoc( ast_id.ast_id, @@ -1089,73 +1091,103 @@ impl DefCollector<'_> { res = ReachedFixedPoint::No; return false; } - Err(UnresolvedMacro { .. }) => (), + Err(UnresolvedMacro { .. }) => {} } } MacroDirectiveKind::Attr { ast_id, mod_item, attr } => { + let file_id = ast_id.ast_id.file_id; + let mut recollect_without = |collector: &mut Self, item_tree| { + // Remove the original directive since we resolved it. + let mod_dir = collector.mod_dirs[&directive.module_id].clone(); + collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); + ModCollector { + def_collector: collector, + macro_depth: directive.depth, + module_id: directive.module_id, + tree_id: TreeId::new(file_id, None), + item_tree, + mod_dir, + } + .collect(&[*mod_item]); + res = ReachedFixedPoint::No; + false + }; + if let Some(ident) = ast_id.path.as_ident() { if let Some(helpers) = self.derive_helpers_in_scope.get(&ast_id.ast_id) { if helpers.contains(ident) { cov_mark::hit!(resolved_derive_helper); - // Resolved to derive helper. Collect the item's attributes again, // starting after the derive helper. - let file_id = ast_id.ast_id.file_id; let item_tree = self.db.file_item_tree(file_id); - let mod_dir = self.mod_dirs[&directive.module_id].clone(); - self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); - ModCollector { - def_collector: &mut *self, - macro_depth: directive.depth, - module_id: directive.module_id, - tree_id: TreeId::new(file_id, None), - item_tree: &item_tree, - mod_dir, - } - .collect(&[*mod_item]); + return recollect_without(self, &item_tree); + } + } + } - // Remove the original directive since we resolved it. + let def = resolver(ast_id.path.clone()).filter(MacroDefId::is_attribute); + if matches!( + def, + Some(MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. }) + if expander.is_derive() + ) { + // Resolved to `#[derive]` + let file_id = ast_id.ast_id.file_id; + let item_tree = self.db.file_item_tree(file_id); + + let ast_id: FileAstId<ast::Item> = match *mod_item { + ModItem::Struct(it) => item_tree[it].ast_id.upcast(), + ModItem::Union(it) => item_tree[it].ast_id.upcast(), + ModItem::Enum(it) => item_tree[it].ast_id.upcast(), + _ => { + // Cannot use derive on this item. + // FIXME: diagnose res = ReachedFixedPoint::No; return false; } + }; + + match attr.parse_derive() { + Some(derive_macros) => { + for path in derive_macros { + let ast_id = AstIdWithPath::new(file_id, ast_id, path); + self.unresolved_macros.push(MacroDirective { + module_id: directive.module_id, + depth: directive.depth + 1, + kind: MacroDirectiveKind::Derive { + ast_id, + derive_attr: attr.id, + }, + }); + } + } + None => { + // FIXME: diagnose + tracing::debug!("malformed derive: {:?}", attr); + } } + + return recollect_without(self, &item_tree); } if !self.db.enable_proc_attr_macros() { return true; } - // Not resolved to a derive helper, so try to resolve as a macro. - match attr_macro_as_call_id( - ast_id, - attr, - self.db, - self.def_map.krate, - &resolver, - ) { + // Not resolved to a derive helper or the derive attribute, so try to resolve as a normal attribute. + match attr_macro_as_call_id(ast_id, attr, self.db, self.def_map.krate, def) { Ok(call_id) => { let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id); // Skip #[test]/#[bench] expansion, which would merely result in more memory usage // due to duplicating functions into macro expansions - if is_builtin_test_or_bench_attr(loc.def) { - let file_id = ast_id.ast_id.file_id; + if matches!( + loc.def.kind, + MacroDefKind::BuiltInAttr(expander, _) + if expander.is_test() || expander.is_bench() + ) { let item_tree = self.db.file_item_tree(file_id); - let mod_dir = self.mod_dirs[&directive.module_id].clone(); - self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); - ModCollector { - def_collector: &mut *self, - macro_depth: directive.depth, - module_id: directive.module_id, - tree_id: TreeId::new(file_id, None), - item_tree: &item_tree, - mod_dir, - } - .collect(&[*mod_item]); - - // Remove the original directive since we resolved it. - res = ReachedFixedPoint::No; - return false; + return recollect_without(self, &item_tree); } if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind { @@ -1171,21 +1203,7 @@ impl DefCollector<'_> { let file_id = ast_id.ast_id.file_id; let item_tree = self.db.file_item_tree(file_id); - let mod_dir = self.mod_dirs[&directive.module_id].clone(); - self.skip_attrs - .insert(InFile::new(file_id, *mod_item), attr.id); - ModCollector { - def_collector: &mut *self, - macro_depth: directive.depth, - module_id: directive.module_id, - tree_id: TreeId::new(file_id, None), - item_tree: &item_tree, - mod_dir, - } - .collect(&[*mod_item]); - - // Remove the macro directive. - return false; + return recollect_without(self, &item_tree); } } @@ -1281,7 +1299,7 @@ impl DefCollector<'_> { for directive in &self.unresolved_macros { match &directive.kind { MacroDirectiveKind::FnLike { ast_id, expand_to } => { - match macro_call_as_call_id( + let macro_call_as_call_id = macro_call_as_call_id( ast_id, *expand_to, self.db, @@ -1297,15 +1315,13 @@ impl DefCollector<'_> { resolved_res.resolved_def.take_macros() }, &mut |_| (), - ) { - Ok(_) => (), - Err(UnresolvedMacro { path }) => { - self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( - directive.module_id, - ast_id.ast_id, - path, - )); - } + ); + if let Err(UnresolvedMacro { path }) = macro_call_as_call_id { + self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( + directive.module_id, + ast_id.ast_id, + path, + )); } } MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => { @@ -1747,26 +1763,23 @@ impl ModCollector<'_, '_> { }); for attr in iter { - if attr.path.as_ident() == Some(&hir_expand::name![derive]) { - self.collect_derive(attr, mod_item); - } else if self.is_builtin_or_registered_attr(&attr.path) { + if self.is_builtin_or_registered_attr(&attr.path) { continue; - } else { - tracing::debug!("non-builtin attribute {}", attr.path); + } + tracing::debug!("non-builtin attribute {}", attr.path); - let ast_id = AstIdWithPath::new( - self.file_id(), - mod_item.ast_id(self.item_tree), - attr.path.as_ref().clone(), - ); - self.def_collector.unresolved_macros.push(MacroDirective { - module_id: self.module_id, - depth: self.macro_depth + 1, - kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item }, - }); + let ast_id = AstIdWithPath::new( + self.file_id(), + mod_item.ast_id(self.item_tree), + attr.path.as_ref().clone(), + ); + self.def_collector.unresolved_macros.push(MacroDirective { + module_id: self.module_id, + depth: self.macro_depth + 1, + kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item }, + }); - return Err(()); - } + return Err(()); } Ok(()) @@ -1800,36 +1813,6 @@ impl ModCollector<'_, '_> { false } - fn collect_derive(&mut self, attr: &Attr, mod_item: ModItem) { - let ast_id: FileAstId<ast::Item> = match mod_item { - ModItem::Struct(it) => self.item_tree[it].ast_id.upcast(), - ModItem::Union(it) => self.item_tree[it].ast_id.upcast(), - ModItem::Enum(it) => self.item_tree[it].ast_id.upcast(), - _ => { - // Cannot use derive on this item. - // FIXME: diagnose - return; - } - }; - - match attr.parse_derive() { - Some(derive_macros) => { - for path in derive_macros { - let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path); - self.def_collector.unresolved_macros.push(MacroDirective { - module_id: self.module_id, - depth: self.macro_depth + 1, - kind: MacroDirectiveKind::Derive { ast_id, derive_attr: attr.id }, - }); - } - } - None => { - // FIXME: diagnose - tracing::debug!("malformed derive: {:?}", attr); - } - } - } - /// If `attrs` registers a procedural macro, collects its definition. fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) { // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere |