diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 852c6d96469..f9d32ffceef 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -991,7 +991,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { _ => false, }; - ModChild { ident, res, vis, span, macro_rules } + ModChild { ident, res, vis, span, macro_rules, reexport_chain: Default::default() } } /// Iterates over all named children of the given module, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 9f16ecbdaa9..dd1e254f405 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -119,6 +119,7 @@ macro_rules! arena_types { [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap, [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>), + [] mod_child: rustc_middle::metadata::ModChild, ]); ) } diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs index 5ff014c7815..fabc6bce731 100644 --- a/compiler/rustc_middle/src/metadata.rs +++ b/compiler/rustc_middle/src/metadata.rs @@ -5,13 +5,34 @@ use rustc_macros::HashStable; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; use rustc_span::Span; +use smallvec::SmallVec; + +/// A simplified version of `ImportKind` from resolve. +/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, HashStable)] +pub enum Reexport { + Single(DefId), + Glob(DefId), + ExternCrate(DefId), + MacroUse, + MacroExport, +} + +impl Reexport { + pub fn id(self) -> Option { + match self { + Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), + Reexport::MacroUse | Reexport::MacroExport => None, + } + } +} /// This structure is supposed to keep enough data to re-create `NameBinding`s for other crates /// during name resolution. Right now the bindings are not recreated entirely precisely so we may /// need to add more data in the future to correctly support macros 2.0, for example. /// Module child can be either a proper item or a reexport (including private imports). /// In case of reexport all the fields describe the reexport item itself, not what it refers to. -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Debug, TyEncodable, TyDecodable, HashStable)] pub struct ModChild { /// Name of the item. pub ident: Ident, @@ -24,4 +45,7 @@ pub struct ModChild { pub span: Span, /// A proper `macro_rules` item (not a reexport). pub macro_rules: bool, + /// Reexport chain linking this module child to its original reexported item. + /// Empty if the module child is a proper item. + pub reexport_chain: SmallVec<[Reexport; 2]>, } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5462ced16d6..24d98665a7b 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -235,7 +235,6 @@ trivial! { rustc_hir::OwnerId, rustc_hir::Upvar, rustc_index::bit_set::FiniteBitSet, - rustc_middle::metadata::ModChild, rustc_middle::middle::dependency_format::Linkage, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 49c41470a15..1f2a90829ec 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -931,7 +931,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) { let parent = self.parent_scope.module; - let ModChild { ident, res, vis, span, macro_rules } = child; + let ModChild { ident, res, vis, span, macro_rules, .. } = child; let res = res.expect_non_local(); let expansion = self.parent_scope.expansion; // Record primary definitions. diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index bc17ce571a7..77bfcb659de 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -17,6 +17,7 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_hir::def::{self, DefKind, PartialRes}; use rustc_middle::metadata::ModChild; +use rustc_middle::metadata::Reexport; use rustc_middle::span_bug; use rustc_middle::ty; use rustc_session::lint::builtin::{ @@ -27,6 +28,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; +use smallvec::SmallVec; use std::cell::Cell; use std::{mem, ptr}; @@ -190,6 +192,17 @@ impl<'a> Import<'a> { ImportKind::MacroUse | ImportKind::MacroExport => None, } } + + fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport { + let to_def_id = |id| r.local_def_id(id).to_def_id(); + match self.kind { + ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)), + ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)), + ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)), + ImportKind::MacroUse => Reexport::MacroUse, + ImportKind::MacroExport => Reexport::MacroExport, + } + } } /// Records information about the resolution of a name in a namespace of a module. @@ -1252,12 +1265,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.for_each_child(self, |this, ident, _, binding| { if let Some(res) = this.is_reexport(binding) { + let mut reexport_chain = SmallVec::new(); + let mut next_binding = binding; + while let NameBindingKind::Import { binding, import, .. } = next_binding.kind { + reexport_chain.push(import.simplify(this)); + next_binding = binding; + } + reexports.push(ModChild { ident, res, vis: binding.vis, span: binding.span, macro_rules: false, + reexport_chain, }); } }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 768f8bb7bc8..87f9483388f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -558,7 +558,7 @@ fn build_module_items( // If we're re-exporting a re-export it may actually re-export something in // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. - for &item in cx.tcx.module_children(did).iter() { + for item in cx.tcx.module_children(did).iter() { if item.vis.is_public() { let res = item.res.expect_non_local(); if let Some(def_id) = res.opt_def_id()