From bbbdbb0e44bb4cea653584017acce4bcda158939 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 23 Nov 2019 18:19:57 +0300 Subject: Move def collector from `rustc` to `rustc_resolve` --- src/librustc/hir/map/def_collector.rs | 350 --------------------------- src/librustc/hir/map/definitions.rs | 11 +- src/librustc/hir/map/mod.rs | 2 - src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/def_collector.rs | 355 ++++++++++++++++++++++++++++ src/librustc_resolve/lib.rs | 1 + 6 files changed, 368 insertions(+), 356 deletions(-) delete mode 100644 src/librustc/hir/map/def_collector.rs create mode 100644 src/librustc_resolve/def_collector.rs (limited to 'src') diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs deleted file mode 100644 index cfd90f50b1b..00000000000 --- a/src/librustc/hir/map/def_collector.rs +++ /dev/null @@ -1,350 +0,0 @@ -use crate::hir::map::definitions::*; -use crate::hir::def_id::DefIndex; - -use syntax::ast::*; -use syntax::visit; -use syntax::symbol::{kw, sym}; -use syntax::token::{self, Token}; -use syntax_pos::hygiene::ExpnId; -use syntax_pos::Span; - -/// Creates `DefId`s for nodes in the AST. -pub struct DefCollector<'a> { - definitions: &'a mut Definitions, - parent_def: DefIndex, - expansion: ExpnId, -} - -impl<'a> DefCollector<'a> { - pub fn new(definitions: &'a mut Definitions, expansion: ExpnId) -> Self { - let parent_def = definitions.invocation_parent(expansion); - DefCollector { definitions, parent_def, expansion } - } - - fn create_def(&mut self, - node_id: NodeId, - data: DefPathData, - span: Span) - -> DefIndex { - let parent_def = self.parent_def; - debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); - self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span) - } - - fn with_parent(&mut self, parent_def: DefIndex, f: F) { - let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); - f(self); - self.parent_def = orig_parent_def; - } - - fn visit_async_fn( - &mut self, - id: NodeId, - name: Name, - span: Span, - header: &FnHeader, - generics: &'a Generics, - decl: &'a FnDecl, - body: &'a Block, - ) { - let (closure_id, return_impl_trait_id) = match header.asyncness.node { - IsAsync::Async { - closure_id, - return_impl_trait_id, - } => (closure_id, return_impl_trait_id), - _ => unreachable!(), - }; - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. - let fn_def_data = DefPathData::ValueNs(name); - let fn_def = self.create_def(id, fn_def_data, span); - return self.with_parent(fn_def, |this| { - this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); - - visit::walk_generics(this, generics); - visit::walk_fn_decl(this, decl); - - let closure_def = this.create_def( - closure_id, DefPathData::ClosureExpr, span, - ); - this.with_parent(closure_def, |this| { - visit::walk_block(this, body); - }) - }) - } - - fn collect_field(&mut self, field: &'a StructField, index: Option) { - if field.is_placeholder { - self.visit_macro_invoc(field.id); - } else { - let name = field.ident.map(|ident| ident.name) - .or_else(|| index.map(sym::integer)) - .unwrap_or_else(|| { - let node_id = NodeId::placeholder_from_expn_id(self.expansion); - sym::integer(self.definitions.placeholder_field_indices[&node_id]) - }); - let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span); - self.with_parent(def, |this| visit::walk_struct_field(this, field)); - } - } - - fn visit_macro_invoc(&mut self, id: NodeId) { - self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); - } -} - -impl<'a> visit::Visitor<'a> for DefCollector<'a> { - fn visit_item(&mut self, i: &'a Item) { - debug!("visit_item: {:?}", i); - - // Pick the def data. This need not be unique, but the more - // information we encapsulate into, the better - let def_data = match &i.kind { - ItemKind::Impl(..) => DefPathData::Impl, - ItemKind::Mod(..) if i.ident.name == kw::Invalid => { - return visit::walk_item(self, i); - } - ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | - ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | - ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | - ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), - ItemKind::Fn(sig, generics, body) if sig.header.asyncness.node.is_async() => { - return self.visit_async_fn( - i.id, - i.ident.name, - i.span, - &sig.header, - generics, - &sig.decl, - body, - ) - } - ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.name), - ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), - ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), - ItemKind::GlobalAsm(..) => DefPathData::Misc, - ItemKind::Use(..) => { - return visit::walk_item(self, i); - } - }; - let def = self.create_def(i.id, def_data, i.span); - - self.with_parent(def, |this| { - match i.kind { - ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { - // If this is a unit or tuple-like struct, register the constructor. - if let Some(ctor_hir_id) = struct_def.ctor_id() { - this.create_def(ctor_hir_id, DefPathData::Ctor, i.span); - } - } - _ => {} - } - visit::walk_item(this, i); - }); - } - - fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { - self.create_def(id, DefPathData::Misc, use_tree.span); - visit::walk_use_tree(self, use_tree, id); - } - - fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { - if let ForeignItemKind::Macro(_) = foreign_item.kind { - return self.visit_macro_invoc(foreign_item.id); - } - - let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.name), - foreign_item.span); - - self.with_parent(def, |this| { - visit::walk_foreign_item(this, foreign_item); - }); - } - - fn visit_variant(&mut self, v: &'a Variant) { - if v.is_placeholder { - return self.visit_macro_invoc(v.id); - } - let def = self.create_def(v.id, - DefPathData::TypeNs(v.ident.name), - v.span); - self.with_parent(def, |this| { - if let Some(ctor_hir_id) = v.data.ctor_id() { - this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); - } - visit::walk_variant(this, v) - }); - } - - fn visit_variant_data(&mut self, data: &'a VariantData) { - // The assumption here is that non-`cfg` macro expansion cannot change field indices. - // It currently holds because only inert attributes are accepted on fields, - // and every such attribute expands into a single field after it's resolved. - for (index, field) in data.fields().iter().enumerate() { - self.collect_field(field, Some(index)); - if field.is_placeholder && field.ident.is_none() { - self.definitions.placeholder_field_indices.insert(field.id, index); - } - } - } - - fn visit_generic_param(&mut self, param: &'a GenericParam) { - if param.is_placeholder { - self.visit_macro_invoc(param.id); - return; - } - let name = param.ident.name; - let def_path_data = match param.kind { - GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), - GenericParamKind::Type { .. } => DefPathData::TypeNs(name), - GenericParamKind::Const { .. } => DefPathData::ValueNs(name), - }; - self.create_def(param.id, def_path_data, param.ident.span); - - visit::walk_generic_param(self, param); - } - - fn visit_trait_item(&mut self, ti: &'a TraitItem) { - let def_data = match ti.kind { - TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name), - TraitItemKind::Type(..) => { - DefPathData::TypeNs(ti.ident.name) - }, - TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), - }; - - let def = self.create_def(ti.id, def_data, ti.span); - self.with_parent(def, |this| visit::walk_trait_item(this, ti)); - } - - fn visit_impl_item(&mut self, ii: &'a ImplItem) { - let def_data = match ii.kind { - ImplItemKind::Method(FnSig { - ref header, - ref decl, - }, ref body) if header.asyncness.node.is_async() => { - return self.visit_async_fn( - ii.id, - ii.ident.name, - ii.span, - header, - &ii.generics, - decl, - body, - ) - } - ImplItemKind::Method(..) | - ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), - ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), - ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), - }; - - let def = self.create_def(ii.id, def_data, ii.span); - self.with_parent(def, |this| visit::walk_impl_item(this, ii)); - } - - fn visit_pat(&mut self, pat: &'a Pat) { - match pat.kind { - PatKind::Mac(..) => return self.visit_macro_invoc(pat.id), - _ => visit::walk_pat(self, pat), - } - } - - fn visit_anon_const(&mut self, constant: &'a AnonConst) { - let def = self.create_def(constant.id, - DefPathData::AnonConst, - constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); - } - - fn visit_expr(&mut self, expr: &'a Expr) { - let parent_def = match expr.kind { - ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(_, asyncness, ..) => { - // Async closures desugar to closures inside of closures, so - // we must create two defs. - let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span); - match asyncness { - IsAsync::Async { closure_id, .. } => - self.create_def(closure_id, DefPathData::ClosureExpr, expr.span), - IsAsync::NotAsync => closure_def, - } - } - ExprKind::Async(_, async_id, _) => - self.create_def(async_id, DefPathData::ClosureExpr, expr.span), - _ => self.parent_def, - }; - - self.with_parent(parent_def, |this| visit::walk_expr(this, expr)); - } - - fn visit_ty(&mut self, ty: &'a Ty) { - match ty.kind { - TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), - TyKind::ImplTrait(node_id, _) => { - self.create_def(node_id, DefPathData::ImplTrait, ty.span); - } - _ => {} - } - visit::walk_ty(self, ty); - } - - fn visit_stmt(&mut self, stmt: &'a Stmt) { - match stmt.kind { - StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id), - _ => visit::walk_stmt(self, stmt), - } - } - - fn visit_token(&mut self, t: Token) { - if let token::Interpolated(nt) = t.kind { - if let token::NtExpr(ref expr) = *nt { - if let ExprKind::Mac(..) = expr.kind { - self.visit_macro_invoc(expr.id); - } - } - } - } - - fn visit_arm(&mut self, arm: &'a Arm) { - if arm.is_placeholder { - self.visit_macro_invoc(arm.id) - } else { - visit::walk_arm(self, arm) - } - } - - fn visit_field(&mut self, f: &'a Field) { - if f.is_placeholder { - self.visit_macro_invoc(f.id) - } else { - visit::walk_field(self, f) - } - } - - fn visit_field_pattern(&mut self, fp: &'a FieldPat) { - if fp.is_placeholder { - self.visit_macro_invoc(fp.id) - } else { - visit::walk_field_pattern(self, fp) - } - } - - fn visit_param(&mut self, p: &'a Param) { - if p.is_placeholder { - self.visit_macro_invoc(p.id) - } else { - visit::walk_param(self, p) - } - } - - // This method is called only when we are visiting an individual field - // after expanding an attribute on it. - fn visit_struct_field(&mut self, field: &'a StructField) { - self.collect_field(field, None); - } -} diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 2b3bc37c87c..91b4971cd92 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -105,7 +105,7 @@ pub struct Definitions { /// we know what parent node that fragment should be attached to thanks to this table. invocation_parents: FxHashMap, /// Indices of unnamed struct or variant fields with unresolved attributes. - pub(super) placeholder_field_indices: NodeMap, + placeholder_field_indices: NodeMap, } /// A unique identifier that we can use to lookup a definition @@ -535,6 +535,15 @@ impl Definitions { let old_parent = self.invocation_parents.insert(invoc_id, parent); assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation"); } + + pub fn placeholder_field_index(&self, node_id: ast::NodeId) -> usize { + self.placeholder_field_indices[&node_id] + } + + pub fn set_placeholder_field_index(&mut self, node_id: ast::NodeId, index: usize) { + let old_index = self.placeholder_field_indices.insert(node_id, index); + assert!(old_index.is_none(), "placeholder field index is reset for a node ID"); + } } impl DefPathData { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 83372dd8ade..fc754c5e675 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1,5 +1,4 @@ use self::collector::NodeCollector; -pub use self::def_collector::DefCollector; pub use self::definitions::{ Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash }; @@ -25,7 +24,6 @@ use syntax_pos::{Span, DUMMY_SP}; pub mod blocks; mod collector; -mod def_collector; pub mod definitions; mod hir_id_validator; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index fd401fde204..a178c603a46 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -5,6 +5,7 @@ //! unexpanded macros in the fragment are visited and registered. //! Imports are also considered items and placed into modules here, but not resolved yet. +use crate::def_collector::collect_definitions; use crate::macros::{LegacyBinding, LegacyScope}; use crate::resolve_imports::ImportDirective; use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; @@ -16,7 +17,6 @@ use crate::{ResolutionError, Determinacy, PathResult, CrateLint}; use rustc::bug; use rustc::hir::def::{self, *}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; -use rustc::hir::map::DefCollector; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -167,8 +167,7 @@ impl<'a> Resolver<'a> { fragment: &AstFragment, parent_scope: ParentScope<'a>, ) -> LegacyScope<'a> { - let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); - fragment.visit_with(&mut def_collector); + collect_definitions(&mut self.definitions, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); visitor.parent_scope.legacy diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs new file mode 100644 index 00000000000..414ea6e9aa1 --- /dev/null +++ b/src/librustc_resolve/def_collector.rs @@ -0,0 +1,355 @@ +use log::debug; +use rustc::hir::map::definitions::*; +use rustc::hir::def_id::DefIndex; +use syntax::ast::*; +use syntax::visit; +use syntax::symbol::{kw, sym}; +use syntax::token::{self, Token}; +use syntax_expand::expand::AstFragment; +use syntax_pos::hygiene::ExpnId; +use syntax_pos::Span; + +crate fn collect_definitions( + definitions: &mut Definitions, + fragment: &AstFragment, + expansion: ExpnId, +) { + let parent_def = definitions.invocation_parent(expansion); + fragment.visit_with(&mut DefCollector { definitions, parent_def, expansion }); +} + +/// Creates `DefId`s for nodes in the AST. +struct DefCollector<'a> { + definitions: &'a mut Definitions, + parent_def: DefIndex, + expansion: ExpnId, +} + +impl<'a> DefCollector<'a> { + fn create_def(&mut self, + node_id: NodeId, + data: DefPathData, + span: Span) + -> DefIndex { + let parent_def = self.parent_def; + debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); + self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span) + } + + fn with_parent(&mut self, parent_def: DefIndex, f: F) { + let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); + f(self); + self.parent_def = orig_parent_def; + } + + fn visit_async_fn( + &mut self, + id: NodeId, + name: Name, + span: Span, + header: &FnHeader, + generics: &'a Generics, + decl: &'a FnDecl, + body: &'a Block, + ) { + let (closure_id, return_impl_trait_id) = match header.asyncness.node { + IsAsync::Async { + closure_id, + return_impl_trait_id, + } => (closure_id, return_impl_trait_id), + _ => unreachable!(), + }; + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. + let fn_def_data = DefPathData::ValueNs(name); + let fn_def = self.create_def(id, fn_def_data, span); + return self.with_parent(fn_def, |this| { + this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); + + visit::walk_generics(this, generics); + visit::walk_fn_decl(this, decl); + + let closure_def = this.create_def( + closure_id, DefPathData::ClosureExpr, span, + ); + this.with_parent(closure_def, |this| { + visit::walk_block(this, body); + }) + }) + } + + fn collect_field(&mut self, field: &'a StructField, index: Option) { + if field.is_placeholder { + self.visit_macro_invoc(field.id); + } else { + let name = field.ident.map(|ident| ident.name) + .or_else(|| index.map(sym::integer)) + .unwrap_or_else(|| { + let node_id = NodeId::placeholder_from_expn_id(self.expansion); + sym::integer(self.definitions.placeholder_field_index(node_id)) + }); + let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span); + self.with_parent(def, |this| visit::walk_struct_field(this, field)); + } + } + + fn visit_macro_invoc(&mut self, id: NodeId) { + self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); + } +} + +impl<'a> visit::Visitor<'a> for DefCollector<'a> { + fn visit_item(&mut self, i: &'a Item) { + debug!("visit_item: {:?}", i); + + // Pick the def data. This need not be unique, but the more + // information we encapsulate into, the better + let def_data = match &i.kind { + ItemKind::Impl(..) => DefPathData::Impl, + ItemKind::Mod(..) if i.ident.name == kw::Invalid => { + return visit::walk_item(self, i); + } + ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | + ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | + ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), + ItemKind::Fn(sig, generics, body) if sig.header.asyncness.node.is_async() => { + return self.visit_async_fn( + i.id, + i.ident.name, + i.span, + &sig.header, + generics, + &sig.decl, + body, + ) + } + ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => + DefPathData::ValueNs(i.ident.name), + ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), + ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), + ItemKind::GlobalAsm(..) => DefPathData::Misc, + ItemKind::Use(..) => { + return visit::walk_item(self, i); + } + }; + let def = self.create_def(i.id, def_data, i.span); + + self.with_parent(def, |this| { + match i.kind { + ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { + // If this is a unit or tuple-like struct, register the constructor. + if let Some(ctor_hir_id) = struct_def.ctor_id() { + this.create_def(ctor_hir_id, DefPathData::Ctor, i.span); + } + } + _ => {} + } + visit::walk_item(this, i); + }); + } + + fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { + self.create_def(id, DefPathData::Misc, use_tree.span); + visit::walk_use_tree(self, use_tree, id); + } + + fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { + if let ForeignItemKind::Macro(_) = foreign_item.kind { + return self.visit_macro_invoc(foreign_item.id); + } + + let def = self.create_def(foreign_item.id, + DefPathData::ValueNs(foreign_item.ident.name), + foreign_item.span); + + self.with_parent(def, |this| { + visit::walk_foreign_item(this, foreign_item); + }); + } + + fn visit_variant(&mut self, v: &'a Variant) { + if v.is_placeholder { + return self.visit_macro_invoc(v.id); + } + let def = self.create_def(v.id, + DefPathData::TypeNs(v.ident.name), + v.span); + self.with_parent(def, |this| { + if let Some(ctor_hir_id) = v.data.ctor_id() { + this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); + } + visit::walk_variant(this, v) + }); + } + + fn visit_variant_data(&mut self, data: &'a VariantData) { + // The assumption here is that non-`cfg` macro expansion cannot change field indices. + // It currently holds because only inert attributes are accepted on fields, + // and every such attribute expands into a single field after it's resolved. + for (index, field) in data.fields().iter().enumerate() { + self.collect_field(field, Some(index)); + if field.is_placeholder && field.ident.is_none() { + self.definitions.set_placeholder_field_index(field.id, index); + } + } + } + + fn visit_generic_param(&mut self, param: &'a GenericParam) { + if param.is_placeholder { + self.visit_macro_invoc(param.id); + return; + } + let name = param.ident.name; + let def_path_data = match param.kind { + GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), + GenericParamKind::Type { .. } => DefPathData::TypeNs(name), + GenericParamKind::Const { .. } => DefPathData::ValueNs(name), + }; + self.create_def(param.id, def_path_data, param.ident.span); + + visit::walk_generic_param(self, param); + } + + fn visit_trait_item(&mut self, ti: &'a TraitItem) { + let def_data = match ti.kind { + TraitItemKind::Method(..) | TraitItemKind::Const(..) => + DefPathData::ValueNs(ti.ident.name), + TraitItemKind::Type(..) => { + DefPathData::TypeNs(ti.ident.name) + }, + TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), + }; + + let def = self.create_def(ti.id, def_data, ti.span); + self.with_parent(def, |this| visit::walk_trait_item(this, ti)); + } + + fn visit_impl_item(&mut self, ii: &'a ImplItem) { + let def_data = match ii.kind { + ImplItemKind::Method(FnSig { + ref header, + ref decl, + }, ref body) if header.asyncness.node.is_async() => { + return self.visit_async_fn( + ii.id, + ii.ident.name, + ii.span, + header, + &ii.generics, + decl, + body, + ) + } + ImplItemKind::Method(..) | + ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), + ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), + ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), + }; + + let def = self.create_def(ii.id, def_data, ii.span); + self.with_parent(def, |this| visit::walk_impl_item(this, ii)); + } + + fn visit_pat(&mut self, pat: &'a Pat) { + match pat.kind { + PatKind::Mac(..) => return self.visit_macro_invoc(pat.id), + _ => visit::walk_pat(self, pat), + } + } + + fn visit_anon_const(&mut self, constant: &'a AnonConst) { + let def = self.create_def(constant.id, + DefPathData::AnonConst, + constant.value.span); + self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + } + + fn visit_expr(&mut self, expr: &'a Expr) { + let parent_def = match expr.kind { + ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), + ExprKind::Closure(_, asyncness, ..) => { + // Async closures desugar to closures inside of closures, so + // we must create two defs. + let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span); + match asyncness { + IsAsync::Async { closure_id, .. } => + self.create_def(closure_id, DefPathData::ClosureExpr, expr.span), + IsAsync::NotAsync => closure_def, + } + } + ExprKind::Async(_, async_id, _) => + self.create_def(async_id, DefPathData::ClosureExpr, expr.span), + _ => self.parent_def, + }; + + self.with_parent(parent_def, |this| visit::walk_expr(this, expr)); + } + + fn visit_ty(&mut self, ty: &'a Ty) { + match ty.kind { + TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), + TyKind::ImplTrait(node_id, _) => { + self.create_def(node_id, DefPathData::ImplTrait, ty.span); + } + _ => {} + } + visit::walk_ty(self, ty); + } + + fn visit_stmt(&mut self, stmt: &'a Stmt) { + match stmt.kind { + StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id), + _ => visit::walk_stmt(self, stmt), + } + } + + fn visit_token(&mut self, t: Token) { + if let token::Interpolated(nt) = t.kind { + if let token::NtExpr(ref expr) = *nt { + if let ExprKind::Mac(..) = expr.kind { + self.visit_macro_invoc(expr.id); + } + } + } + } + + fn visit_arm(&mut self, arm: &'a Arm) { + if arm.is_placeholder { + self.visit_macro_invoc(arm.id) + } else { + visit::walk_arm(self, arm) + } + } + + fn visit_field(&mut self, f: &'a Field) { + if f.is_placeholder { + self.visit_macro_invoc(f.id) + } else { + visit::walk_field(self, f) + } + } + + fn visit_field_pattern(&mut self, fp: &'a FieldPat) { + if fp.is_placeholder { + self.visit_macro_invoc(fp.id) + } else { + visit::walk_field_pattern(self, fp) + } + } + + fn visit_param(&mut self, p: &'a Param) { + if p.is_placeholder { + self.visit_macro_invoc(p.id) + } else { + visit::walk_param(self, p) + } + } + + // This method is called only when we are visiting an individual field + // after expanding an attribute on it. + fn visit_struct_field(&mut self, field: &'a StructField) { + self.collect_field(field, None); + } +} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c49db39643b..347b7288565 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -68,6 +68,7 @@ use rustc_error_codes::*; type Res = def::Res; +mod def_collector; mod diagnostics; mod late; mod macros; -- cgit 1.4.1-3-g733a5