diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2021-02-13 20:41:02 +0100 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2021-03-12 22:48:32 +0100 |
| commit | 445b4e379ca487b268ff6360b193feb28106b5ac (patch) | |
| tree | 563a7f91bec7cda5ffcad5cbfd6a5c57d96dbd26 /compiler/rustc_resolve/src | |
| parent | 17a07d71bfd692f9b2dad2a566aff52bf3d4bfe2 (diff) | |
| download | rust-445b4e379ca487b268ff6360b193feb28106b5ac.tar.gz rust-445b4e379ca487b268ff6360b193feb28106b5ac.zip | |
Make def_key and HIR parenting consistent.
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 89 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 2 |
3 files changed, 82 insertions, 22 deletions
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 727d6ab53d8..6ef5e1179de 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,4 +1,4 @@ -use crate::Resolver; +use crate::{ImplTraitContext, Resolver}; use rustc_ast::visit::{self, FnKind}; use rustc_ast::walk_list; use rustc_ast::*; @@ -16,14 +16,15 @@ crate fn collect_definitions( fragment: &AstFragment, expansion: ExpnId, ) { - let parent_def = resolver.invocation_parents[&expansion]; - fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion }); + let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion]; + fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context }); } /// Creates `DefId`s for nodes in the AST. struct DefCollector<'a, 'b> { resolver: &'a mut Resolver<'b>, parent_def: LocalDefId, + impl_trait_context: ImplTraitContext, expansion: ExpnId, } @@ -40,6 +41,16 @@ impl<'a, 'b> DefCollector<'a, 'b> { self.parent_def = orig_parent_def; } + fn with_impl_trait<F: FnOnce(&mut Self)>( + &mut self, + impl_trait_context: ImplTraitContext, + f: F, + ) { + let orig_itc = std::mem::replace(&mut self.impl_trait_context, impl_trait_context); + f(self); + self.impl_trait_context = orig_itc; + } + fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) { let index = |this: &Self| { index.unwrap_or_else(|| { @@ -60,8 +71,9 @@ impl<'a, 'b> DefCollector<'a, 'b> { } fn visit_macro_invoc(&mut self, id: NodeId) { + let id = id.placeholder_to_expn_id(); let old_parent = - self.resolver.invocation_parents.insert(id.placeholder_to_expn_id(), self.parent_def); + self.resolver.invocation_parents.insert(id, (self.parent_def, self.impl_trait_context)); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } } @@ -103,29 +115,37 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { 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); + this.with_impl_trait(ImplTraitContext::Existential, |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); + visit::walk_item(this, i); + }) }); } fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let FnKind::Fn(_, _, sig, _, body) = fn_kind { if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness { - self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); + let return_impl_trait_id = + self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. Besides that, // we must mirror everything that `visit::walk_fn` below does. self.visit_fn_header(&sig.header); - visit::walk_fn_decl(self, &sig.decl); + for param in &sig.decl.inputs { + self.visit_param(param); + } + self.with_parent(return_impl_trait_id, |this| { + this.visit_fn_ret_ty(&sig.decl.output) + }); let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); self.with_parent(closure_def, |this| walk_list!(this, visit_block, body)); return; @@ -137,6 +157,14 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { self.create_def(id, DefPathData::Misc, use_tree.span); + match use_tree.kind { + UseTreeKind::Simple(_, id1, id2) => { + self.create_def(id1, DefPathData::Misc, use_tree.prefix.span); + self.create_def(id2, DefPathData::Misc, use_tree.prefix.span); + } + UseTreeKind::Glob => (), + UseTreeKind::Nested(..) => {} + } visit::walk_use_tree(self, use_tree, id); } @@ -191,7 +219,15 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { }; self.create_def(param.id, def_path_data, param.ident.span); - visit::walk_generic_param(self, param); + // impl-Trait can happen inside generic parameters, like + // ``` + // fn foo<U: Iterator<Item = impl Clone>>() {} + // ``` + // + // In that case, the impl-trait is lowered as an additional generic parameter. + self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { + visit::walk_generic_param(this, param) + }); } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { @@ -244,8 +280,19 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { match ty.kind { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), TyKind::ImplTrait(node_id, _) => { - let parent_def = self.create_def(node_id, DefPathData::ImplTrait, ty.span); - self.with_parent(parent_def, |this| visit::walk_ty(this, ty)); + let parent_def = match self.impl_trait_context { + ImplTraitContext::Universal(item_def) => self.resolver.create_def( + item_def, + node_id, + DefPathData::ImplTrait, + self.expansion, + ty.span, + ), + ImplTraitContext::Existential => { + self.create_def(node_id, DefPathData::ImplTrait, ty.span) + } + }; + self.with_parent(parent_def, |this| visit::walk_ty(this, ty)) } _ => visit::walk_ty(self, ty), } @@ -275,7 +322,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { } fn visit_param(&mut self, p: &'a Param) { - if p.is_placeholder { self.visit_macro_invoc(p.id) } else { visit::walk_param(self, p) } + if p.is_placeholder { + self.visit_macro_invoc(p.id) + } else { + self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { + visit::walk_param(this, p) + }) + } } // This method is called only when we are visiting an individual field diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2ce54658c0b..ccfb5ff3aa0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -156,6 +156,12 @@ impl<'a> ParentScope<'a> { } } +#[derive(Copy, Debug, Clone)] +enum ImplTraitContext { + Existential, + Universal(LocalDefId), +} + #[derive(Eq)] struct BindingError { name: Symbol, @@ -989,8 +995,9 @@ pub struct Resolver<'a> { /// Indices of unnamed struct or variant fields with unresolved attributes. placeholder_field_indices: FxHashMap<NodeId, usize>, /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` - /// we know what parent node that fragment should be attached to thanks to this table. - invocation_parents: FxHashMap<ExpnId, LocalDefId>, + /// we know what parent node that fragment should be attached to thanks to this table, + /// and how the `impl Trait` fragments were introduced. + invocation_parents: FxHashMap<ExpnId, (LocalDefId, ImplTraitContext)>, next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// Some way to know that we are in a *trait* impl in `visit_assoc_item`. @@ -1205,7 +1212,7 @@ impl<'a> Resolver<'a> { node_id_to_def_id.insert(CRATE_NODE_ID, root); let mut invocation_parents = FxHashMap::default(); - invocation_parents.insert(ExpnId::root(), root); + invocation_parents.insert(ExpnId::root(), (root, ImplTraitContext::Existential)); let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session .opts diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index f7010ca94bd..2d149c476a6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -326,7 +326,7 @@ impl<'a> ResolverExpand for Resolver<'a> { // nearest closing item - we should try to return the closest parent of the ExpnId self.invocation_parents .get(&expn_id) - .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id]) + .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]) } fn has_derive_copy(&self, expn_id: ExpnId) -> bool { |
