From bcd13d4b8c3cd6d557e7ca278c80397a10dae87f Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 30 Oct 2019 19:00:27 -0300
Subject: [PATCH 1/5] Move CrateMetadata impl block to where CrateMetadata is
 defined

---
 src/librustc_metadata/cstore.rs  | 998 ++++++++++++++++++++++++++++++-
 src/librustc_metadata/decoder.rs | 991 +-----------------------------
 2 files changed, 993 insertions(+), 996 deletions(-)

diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index b7596d2018f7e..459350ad074d3 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -1,21 +1,35 @@
 // The crate store - a central repo for information collected about external
 // crates and libraries
-
-use crate::schema;
-use rustc::dep_graph::DepNodeIndex;
-use rustc::hir::def_id::{CrateNum, DefIndex};
+use crate::schema::{self, *};
+use log::debug;
+use proc_macro::bridge::client::ProcMacro;
+use rustc::dep_graph::{self, DepNodeIndex};
+use rustc::hir;
+use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir::map::definitions::DefPathTable;
-use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate};
+use rustc::middle::lang_items;
+use rustc::middle::cstore::{
+    CrateSource, DepKind, ExternCrate, ForeignModule, LinkagePreference, NativeLibrary
+};
+use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
+use rustc::mir::{Body, Promoted};
 use rustc::mir::interpret::AllocDecodingState;
-use rustc_index::vec::IndexVec;
 use rustc::util::nodemap::FxHashMap;
+use rustc::session::Session;
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::{Lrc, Lock, MetadataRef, Once, AtomicCell};
 use rustc_data_structures::svh::Svh;
-use syntax::ast;
+use rustc_index::vec::IndexVec;
+use syntax::ast::{self, Ident};
+use syntax::attr;
 use syntax::edition::Edition;
-use syntax_expand::base::SyntaxExtension;
-use syntax_pos;
-use proc_macro::bridge::client::ProcMacro;
+use syntax::source_map::{self, respan, Spanned};
+use syntax_expand::base::{SyntaxExtensionKind, SyntaxExtension};
+use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
+use syntax_pos::{self, Span, Pos, DUMMY_SP, hygiene::MacroKind};
+use syntax_pos::symbol::{Symbol, sym};
 
 pub use crate::cstore_impl::{provide, provide_extern};
 
@@ -98,6 +112,970 @@ crate struct CrateMetadata {
     crate extern_crate: Lock<Option<ExternCrate>>,
 }
 
+impl<'a, 'tcx> CrateMetadata {
+    crate fn is_proc_macro_crate(&self) -> bool {
+        self.root.proc_macro_decls_static.is_some()
+    }
+
+    fn is_proc_macro(&self, id: DefIndex) -> bool {
+        self.is_proc_macro_crate() &&
+            self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some()
+    }
+
+    fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind<'tcx>> {
+        self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self))
+    }
+
+    fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> {
+        assert!(!self.is_proc_macro(item_id));
+        self.maybe_kind(item_id).unwrap_or_else(|| {
+            bug!(
+                "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
+                item_id,
+                self.root.name,
+                self.cnum,
+            )
+        })
+    }
+
+    fn local_def_id(&self, index: DefIndex) -> DefId {
+        DefId {
+            krate: self.cnum,
+            index,
+        }
+    }
+
+    fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
+        // DefIndex's in root.proc_macro_data have a one-to-one correspondence
+        // with items in 'raw_proc_macros'.
+        // NOTE: If you update the order of macros in 'proc_macro_data' for any reason,
+        // you must also update src/libsyntax_ext/proc_macro_harness.rs
+        // Failing to do so will result in incorrect data being associated
+        // with proc macros when deserialized.
+        let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
+        &self.raw_proc_macros.unwrap()[pos]
+    }
+
+    crate fn item_name(&self, item_index: DefIndex) -> Symbol {
+        if !self.is_proc_macro(item_index) {
+            self.def_key(item_index)
+                .disambiguated_data
+                .data
+                .get_opt_name()
+                .expect("no name in item_name")
+        } else {
+            Symbol::intern(self.raw_proc_macro(item_index).name())
+        }
+    }
+
+    crate fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
+        if !self.is_proc_macro(index) {
+            self.kind(index).def_kind()
+        } else {
+            Some(DefKind::Macro(
+                macro_kind(self.raw_proc_macro(index))
+            ))
+        }
+    }
+
+    crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
+        self.root.per_def.span.get(self, index).unwrap().decode((self, sess))
+    }
+
+    crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
+        let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
+            ProcMacro::CustomDerive { trait_name, attributes, client } => {
+                let helper_attrs =
+                    attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
+                (
+                    trait_name,
+                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })),
+                    helper_attrs,
+                )
+            }
+            ProcMacro::Attr { name, client } => (
+                name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
+            ),
+            ProcMacro::Bang { name, client } => (
+                name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
+            )
+        };
+
+        SyntaxExtension::new(
+            &sess.parse_sess,
+            kind,
+            self.get_span(id, sess),
+            helper_attrs,
+            self.root.edition,
+            Symbol::intern(name),
+            &self.get_item_attrs(id, sess),
+        )
+    }
+
+    crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
+        match self.kind(item_id) {
+            EntryKind::Trait(data) => {
+                let data = data.decode((self, sess));
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  data.unsafety,
+                                  data.paren_sugar,
+                                  data.has_auto_impl,
+                                  data.is_marker,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            EntryKind::TraitAlias => {
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  hir::Unsafety::Normal,
+                                  false,
+                                  false,
+                                  false,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        }
+    }
+
+    fn get_variant(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        kind: &EntryKind<'_>,
+        index: DefIndex,
+        parent_did: DefId,
+    ) -> ty::VariantDef {
+        let data = match kind {
+            EntryKind::Variant(data) |
+            EntryKind::Struct(data, _) |
+            EntryKind::Union(data, _) => data.decode(self),
+            _ => bug!(),
+        };
+
+        let adt_kind = match kind {
+            EntryKind::Variant(_) => ty::AdtKind::Enum,
+            EntryKind::Struct(..) => ty::AdtKind::Struct,
+            EntryKind::Union(..) => ty::AdtKind::Union,
+            _ => bug!(),
+        };
+
+        let variant_did = if adt_kind == ty::AdtKind::Enum {
+            Some(self.local_def_id(index))
+        } else {
+            None
+        };
+        let ctor_did = data.ctor.map(|index| self.local_def_id(index));
+
+        ty::VariantDef::new(
+            tcx,
+            Ident::with_dummy_span(self.item_name(index)),
+            variant_did,
+            ctor_did,
+            data.discr,
+            self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty())
+                .decode(self).map(|index| ty::FieldDef {
+                    did: self.local_def_id(index),
+                    ident: Ident::with_dummy_span(self.item_name(index)),
+                    vis: self.get_visibility(index),
+                }).collect(),
+            data.ctor_kind,
+            adt_kind,
+            parent_did,
+            false,
+        )
+    }
+
+    crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
+        let kind = self.kind(item_id);
+        let did = self.local_def_id(item_id);
+
+        let (adt_kind, repr) = match kind {
+            EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
+            EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
+            EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
+            _ => bug!("get_adt_def called on a non-ADT {:?}", did),
+        };
+
+        let variants = if let ty::AdtKind::Enum = adt_kind {
+            self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty())
+                .decode(self)
+                .map(|index| {
+                    self.get_variant(tcx, &self.kind(index), index, did)
+                })
+                .collect()
+        } else {
+            std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect()
+        };
+
+        tcx.alloc_adt_def(did, adt_kind, variants, repr)
+    }
+
+    crate fn get_predicates(
+        &self,
+        item_id: DefIndex,
+        tcx: TyCtxt<'tcx>,
+    ) -> ty::GenericPredicates<'tcx> {
+        self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx))
+    }
+
+    crate fn get_predicates_defined_on(
+        &self,
+        item_id: DefIndex,
+        tcx: TyCtxt<'tcx>,
+    ) -> ty::GenericPredicates<'tcx> {
+        self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx))
+    }
+
+    crate fn get_super_predicates(
+        &self,
+        item_id: DefIndex,
+        tcx: TyCtxt<'tcx>,
+    ) -> ty::GenericPredicates<'tcx> {
+        self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
+    }
+
+    crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
+        self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess))
+    }
+
+    crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx))
+    }
+
+    crate fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
+        match self.is_proc_macro(id) {
+            true => self.root.proc_macro_stability.clone(),
+            false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)),
+        }
+    }
+
+    crate fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
+        self.root.per_def.deprecation.get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .map(|depr| depr.decode(self))
+    }
+
+    crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
+        match self.is_proc_macro(id) {
+            true => ty::Visibility::Public,
+            false => self.root.per_def.visibility.get(self, id).unwrap().decode(self),
+        }
+    }
+
+    fn get_impl_data(&self, id: DefIndex) -> ImplData {
+        match self.kind(id) {
+            EntryKind::Impl(data) => data.decode(self),
+            _ => bug!(),
+        }
+    }
+
+    crate fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
+        self.get_impl_data(id).parent_impl
+    }
+
+    crate fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
+        self.get_impl_data(id).polarity
+    }
+
+    crate fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
+        self.get_impl_data(id).defaultness
+    }
+
+    crate fn get_coerce_unsized_info(
+        &self,
+        id: DefIndex,
+    ) -> Option<ty::adjustment::CoerceUnsizedInfo> {
+        self.get_impl_data(id).coerce_unsized_info
+    }
+
+    crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
+        self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
+    }
+
+    /// Iterates over all the stability attributes in the given crate.
+    crate fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option<ast::Name>)] {
+        // FIXME: For a proc macro crate, not sure whether we should return the "host"
+        // features or an empty Vec. Both don't cause ICEs.
+        tcx.arena.alloc_from_iter(self.root
+            .lib_features
+            .decode(self))
+    }
+
+    /// Iterates over the language items in the given crate.
+    crate fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
+        if self.is_proc_macro_crate() {
+            // Proc macro crates do not export any lang-items to the target.
+            &[]
+        } else {
+            tcx.arena.alloc_from_iter(self.root
+                .lang_items
+                .decode(self)
+                .map(|(def_index, index)| (self.local_def_id(def_index), index)))
+        }
+    }
+
+    /// Iterates over the diagnostic items in the given crate.
+    crate fn get_diagnostic_items(
+        &self,
+        tcx: TyCtxt<'tcx>,
+    ) -> &'tcx FxHashMap<Symbol, DefId> {
+        tcx.arena.alloc(if self.is_proc_macro_crate() {
+            // Proc macro crates do not export any diagnostic-items to the target.
+            Default::default()
+        } else {
+            self.root
+                .diagnostic_items
+                .decode(self)
+                .map(|(name, def_index)| (name, self.local_def_id(def_index)))
+                .collect()
+        })
+    }
+
+    /// Iterates over each child of the given item.
+    crate fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
+        where F: FnMut(def::Export<hir::HirId>)
+    {
+        if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) {
+            /* If we are loading as a proc macro, we want to return the view of this crate
+             * as a proc macro crate.
+             */
+            if id == CRATE_DEF_INDEX {
+                for def_index in proc_macros_ids {
+                    let raw_macro = self.raw_proc_macro(def_index);
+                    let res = Res::Def(
+                        DefKind::Macro(macro_kind(raw_macro)),
+                        self.local_def_id(def_index),
+                    );
+                    let ident = Ident::from_str(raw_macro.name());
+                    callback(def::Export {
+                        ident: ident,
+                        res: res,
+                        vis: ty::Visibility::Public,
+                        span: DUMMY_SP,
+                    });
+                }
+            }
+            return
+        }
+
+        // Find the item.
+        let kind = match self.maybe_kind(id) {
+            None => return,
+            Some(kind) => kind,
+        };
+
+        // Iterate over all children.
+        let macros_only = self.dep_kind.lock().macros_only();
+        let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty());
+        for child_index in children.decode((self, sess)) {
+            if macros_only {
+                continue
+            }
+
+            // Get the item.
+            if let Some(child_kind) = self.maybe_kind(child_index) {
+                match child_kind {
+                    EntryKind::MacroDef(..) => {}
+                    _ if macros_only => continue,
+                    _ => {}
+                }
+
+                // Hand off the item to the callback.
+                match child_kind {
+                    // FIXME(eddyb) Don't encode these in children.
+                    EntryKind::ForeignMod => {
+                        let child_children =
+                            self.root.per_def.children.get(self, child_index)
+                                .unwrap_or(Lazy::empty());
+                        for child_index in child_children.decode((self, sess)) {
+                            if let Some(kind) = self.def_kind(child_index) {
+                                callback(def::Export {
+                                    res: Res::Def(kind, self.local_def_id(child_index)),
+                                    ident: Ident::with_dummy_span(self.item_name(child_index)),
+                                    vis: self.get_visibility(child_index),
+                                    span: self.root.per_def.span.get(self, child_index).unwrap()
+                                        .decode((self, sess)),
+                                });
+                            }
+                        }
+                        continue;
+                    }
+                    EntryKind::Impl(_) => continue,
+
+                    _ => {}
+                }
+
+                let def_key = self.def_key(child_index);
+                let span = self.get_span(child_index, sess);
+                if let (Some(kind), Some(name)) =
+                    (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) {
+                    let ident = Ident::with_dummy_span(name);
+                    let vis = self.get_visibility(child_index);
+                    let def_id = self.local_def_id(child_index);
+                    let res = Res::Def(kind, def_id);
+                    callback(def::Export { res, ident, vis, span });
+                    // For non-re-export structs and variants add their constructors to children.
+                    // Re-export lists automatically contain constructors when necessary.
+                    match kind {
+                        DefKind::Struct => {
+                            if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) {
+                                let ctor_kind = self.get_ctor_kind(child_index);
+                                let ctor_res = Res::Def(
+                                    DefKind::Ctor(CtorOf::Struct, ctor_kind),
+                                    ctor_def_id,
+                                );
+                                let vis = self.get_visibility(ctor_def_id.index);
+                                callback(def::Export { res: ctor_res, vis, ident, span });
+                            }
+                        }
+                        DefKind::Variant => {
+                            // Braced variants, unlike structs, generate unusable names in
+                            // value namespace, they are reserved for possible future use.
+                            // It's ok to use the variant's id as a ctor id since an
+                            // error will be reported on any use of such resolution anyway.
+                            let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
+                            let ctor_kind = self.get_ctor_kind(child_index);
+                            let ctor_res = Res::Def(
+                                DefKind::Ctor(CtorOf::Variant, ctor_kind),
+                                ctor_def_id,
+                            );
+                            let mut vis = self.get_visibility(ctor_def_id.index);
+                            if ctor_def_id == def_id && vis == ty::Visibility::Public {
+                                // For non-exhaustive variants lower the constructor visibility to
+                                // within the crate. We only need this for fictive constructors,
+                                // for other constructors correct visibilities
+                                // were already encoded in metadata.
+                                let attrs = self.get_item_attrs(def_id.index, sess);
+                                if attr::contains_name(&attrs, sym::non_exhaustive) {
+                                    let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
+                                    vis = ty::Visibility::Restricted(crate_def_id);
+                                }
+                            }
+                            callback(def::Export { res: ctor_res, ident, vis, span });
+                        }
+                        _ => {}
+                    }
+                }
+            }
+        }
+
+        if let EntryKind::Mod(data) = kind {
+            for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
+                match exp.res {
+                    Res::Def(DefKind::Macro(..), _) => {}
+                    _ if macros_only => continue,
+                    _ => {}
+                }
+                callback(exp);
+            }
+        }
+    }
+
+    crate fn is_item_mir_available(&self, id: DefIndex) -> bool {
+        !self.is_proc_macro(id) &&
+            self.root.per_def.mir.get(self, id).is_some()
+    }
+
+    crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
+        self.root.per_def.mir.get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .unwrap_or_else(|| {
+                bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id))
+            })
+            .decode((self, tcx))
+    }
+
+    crate fn get_promoted_mir(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        id: DefIndex,
+    ) -> IndexVec<Promoted, Body<'tcx>> {
+        self.root.per_def.promoted_mir.get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .unwrap_or_else(|| {
+                bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id))
+            })
+            .decode((self, tcx))
+    }
+
+    crate fn mir_const_qualif(&self, id: DefIndex) -> u8 {
+        match self.kind(id) {
+            EntryKind::Const(qualif, _) |
+            EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) |
+            EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => {
+                qualif.mir
+            }
+            _ => bug!(),
+        }
+    }
+
+    crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
+        let def_key = self.def_key(id);
+        let parent = self.local_def_id(def_key.parent.unwrap());
+        let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
+
+        let (kind, container, has_self) = match self.kind(id) {
+            EntryKind::AssocConst(container, _, _) => {
+                (ty::AssocKind::Const, container, false)
+            }
+            EntryKind::Method(data) => {
+                let data = data.decode(self);
+                (ty::AssocKind::Method, data.container, data.has_self)
+            }
+            EntryKind::AssocType(container) => {
+                (ty::AssocKind::Type, container, false)
+            }
+            EntryKind::AssocOpaqueTy(container) => {
+                (ty::AssocKind::OpaqueTy, container, false)
+            }
+            _ => bug!("cannot get associated-item of `{:?}`", def_key)
+        };
+
+        ty::AssocItem {
+            ident: Ident::with_dummy_span(name),
+            kind,
+            vis: self.get_visibility(id),
+            defaultness: container.defaultness(),
+            def_id: self.local_def_id(id),
+            container: container.with_def_id(parent),
+            method_has_self_argument: has_self
+        }
+    }
+
+    crate fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
+        self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty())
+            .decode(self).collect()
+    }
+
+    crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
+        match self.kind(node_id) {
+            EntryKind::Struct(data, _) |
+            EntryKind::Union(data, _) |
+            EntryKind::Variant(data) => data.decode(self).ctor_kind,
+            _ => CtorKind::Fictive,
+        }
+    }
+
+    crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
+        match self.kind(node_id) {
+            EntryKind::Struct(data, _) => {
+                data.decode(self).ctor.map(|index| self.local_def_id(index))
+            }
+            EntryKind::Variant(data) => {
+                data.decode(self).ctor.map(|index| self.local_def_id(index))
+            }
+            _ => None,
+        }
+    }
+
+    crate fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
+        // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
+        // we assume that someone passing in a tuple struct ctor is actually wanting to
+        // look at the definition
+        let def_key = self.def_key(node_id);
+        let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor {
+            def_key.parent.unwrap()
+        } else {
+            node_id
+        };
+
+        Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty())
+            .decode((self, sess))
+            .collect::<Vec<_>>())
+    }
+
+    crate fn get_struct_field_names(
+        &self,
+        id: DefIndex,
+        sess: &Session,
+    ) -> Vec<Spanned<ast::Name>> {
+        self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty())
+            .decode(self)
+            .map(|index| respan(self.get_span(index, sess), self.item_name(index)))
+            .collect()
+    }
+
+    // Translate a DefId from the current compilation environment to a DefId
+    // for an external crate.
+    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
+        for (local, &global) in self.cnum_map.iter_enumerated() {
+            if global == did.krate {
+                return Some(DefId {
+                    krate: local,
+                    index: did.index,
+                });
+            }
+        }
+
+        None
+    }
+
+    crate fn get_inherent_implementations_for_type(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        id: DefIndex,
+    ) -> &'tcx [DefId] {
+        tcx.arena.alloc_from_iter(
+            self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty())
+                .decode(self)
+                .map(|index| self.local_def_id(index))
+        )
+    }
+
+    crate fn get_implementations_for_trait(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        filter: Option<DefId>,
+    ) -> &'tcx [DefId] {
+        if self.is_proc_macro_crate() {
+            // proc-macro crates export no trait impls.
+            return &[]
+        }
+
+        // Do a reverse lookup beforehand to avoid touching the crate_num
+        // hash map in the loop below.
+        let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
+            Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
+            Some(None) => return &[],
+            None => None,
+        };
+
+        if let Some(filter) = filter {
+            if let Some(impls) = self.trait_impls.get(&filter) {
+                tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
+            } else {
+                &[]
+            }
+        } else {
+            tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| {
+                impls.decode(self).map(|idx| self.local_def_id(idx))
+            }))
+        }
+    }
+
+    crate fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
+        let def_key = self.def_key(id);
+        match def_key.disambiguated_data.data {
+            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
+            // Not an associated item
+            _ => return None,
+        }
+        def_key.parent.and_then(|parent_index| {
+            match self.kind(parent_index) {
+                EntryKind::Trait(_) |
+                EntryKind::TraitAlias => Some(self.local_def_id(parent_index)),
+                _ => None,
+            }
+        })
+    }
+
+
+    crate fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
+        if self.is_proc_macro_crate() {
+            // Proc macro crates do not have any *target* native libraries.
+            vec![]
+        } else {
+            self.root.native_libraries.decode((self, sess)).collect()
+        }
+    }
+
+    crate fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
+        if self.is_proc_macro_crate() {
+            // Proc macro crates do not have any *target* foreign modules.
+            &[]
+        } else {
+            tcx.arena.alloc_from_iter(self.root.foreign_modules.decode((self, tcx.sess)))
+        }
+    }
+
+    crate fn get_dylib_dependency_formats(
+        &self,
+        tcx: TyCtxt<'tcx>,
+    ) -> &'tcx [(CrateNum, LinkagePreference)] {
+        tcx.arena.alloc_from_iter(self.root
+            .dylib_dependency_formats
+            .decode(self)
+            .enumerate()
+            .flat_map(|(i, link)| {
+                let cnum = CrateNum::new(i + 1);
+                link.map(|link| (self.cnum_map[cnum], link))
+            }))
+    }
+
+    crate fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
+        if self.is_proc_macro_crate() {
+            // Proc macro crates do not depend on any target weak lang-items.
+            &[]
+        } else {
+            tcx.arena.alloc_from_iter(self.root
+                .lang_items_missing
+                .decode(self))
+        }
+    }
+
+    crate fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
+        let param_names = match self.kind(id) {
+            EntryKind::Fn(data) |
+            EntryKind::ForeignFn(data) => data.decode(self).param_names,
+            EntryKind::Method(data) => data.decode(self).fn_data.param_names,
+            _ => Lazy::empty(),
+        };
+        param_names.decode(self).collect()
+    }
+
+    crate fn exported_symbols(
+        &self,
+        tcx: TyCtxt<'tcx>,
+    ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
+        if self.is_proc_macro_crate() {
+            // If this crate is a custom derive crate, then we're not even going to
+            // link those in so we skip those crates.
+            vec![]
+        } else {
+            self.root.exported_symbols.decode((self, tcx)).collect()
+        }
+    }
+
+    crate fn get_rendered_const(&self, id: DefIndex) -> String {
+        match self.kind(id) {
+            EntryKind::Const(_, data) |
+            EntryKind::AssocConst(_, _, data) => data.decode(self).0,
+            _ => bug!(),
+        }
+    }
+
+    crate fn get_macro(&self, id: DefIndex) -> MacroDef {
+        match self.kind(id) {
+            EntryKind::MacroDef(macro_def) => macro_def.decode(self),
+            _ => bug!(),
+        }
+    }
+
+    crate fn is_const_fn_raw(&self, id: DefIndex) -> bool {
+        let constness = match self.kind(id) {
+            EntryKind::Method(data) => data.decode(self).fn_data.constness,
+            EntryKind::Fn(data) => data.decode(self).constness,
+            EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const,
+            _ => hir::Constness::NotConst,
+        };
+        constness == hir::Constness::Const
+    }
+
+    crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
+         match self.kind(id) {
+            EntryKind::Fn(data) => data.decode(self).asyncness,
+            EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
+            EntryKind::ForeignFn(data) => data.decode(self).asyncness,
+            _ => bug!("asyncness: expected function kind"),
+        }
+    }
+
+    crate fn is_foreign_item(&self, id: DefIndex) -> bool {
+        match self.kind(id) {
+            EntryKind::ForeignImmStatic |
+            EntryKind::ForeignMutStatic |
+            EntryKind::ForeignFn(_) => true,
+            _ => false,
+        }
+    }
+
+    crate fn static_mutability(&self, id: DefIndex) -> Option<hir::Mutability> {
+        match self.kind(id) {
+            EntryKind::ImmStatic |
+            EntryKind::ForeignImmStatic => Some(hir::MutImmutable),
+            EntryKind::MutStatic |
+            EntryKind::ForeignMutStatic => Some(hir::MutMutable),
+            _ => None,
+        }
+    }
+
+    crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+        self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx))
+    }
+
+    #[inline]
+    crate fn def_key(&self, index: DefIndex) -> DefKey {
+        let mut key = self.def_path_table.def_key(index);
+        if self.is_proc_macro(index) {
+            let name = self.raw_proc_macro(index).name();
+            key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
+        }
+        key
+    }
+
+    // Returns the path leading to the thing with this `id`.
+    crate fn def_path(&self, id: DefIndex) -> DefPath {
+        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
+        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
+    }
+
+    #[inline]
+    crate fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+        self.def_path_table.def_path_hash(index)
+    }
+
+    /// Imports the source_map from an external crate into the source_map of the crate
+    /// currently being compiled (the "local crate").
+    ///
+    /// The import algorithm works analogous to how AST items are inlined from an
+    /// external crate's metadata:
+    /// For every SourceFile in the external source_map an 'inline' copy is created in the
+    /// local source_map. The correspondence relation between external and local
+    /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this
+    /// function. When an item from an external crate is later inlined into this
+    /// crate, this correspondence information is used to translate the span
+    /// information of the inlined item so that it refers the correct positions in
+    /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
+    ///
+    /// The import algorithm in the function below will reuse SourceFiles already
+    /// existing in the local source_map. For example, even if the SourceFile of some
+    /// source file of libstd gets imported many times, there will only ever be
+    /// one SourceFile object for the corresponding file in the local source_map.
+    ///
+    /// Note that imported SourceFiles do not actually contain the source code of the
+    /// file they represent, just information about length, line breaks, and
+    /// multibyte characters. This information is enough to generate valid debuginfo
+    /// for items inlined from other crates.
+    ///
+    /// Proc macro crates don't currently export spans, so this function does not have
+    /// to work for them.
+    pub(super) fn imported_source_files(
+        &'a self,
+        local_source_map: &source_map::SourceMap,
+    ) -> &[ImportedSourceFile] {
+        self.source_map_import_info.init_locking(|| {
+            let external_source_map = self.root.source_map.decode(self);
+
+            external_source_map.map(|source_file_to_import| {
+                // We can't reuse an existing SourceFile, so allocate a new one
+                // containing the information we need.
+                let syntax_pos::SourceFile { name,
+                                          name_was_remapped,
+                                          src_hash,
+                                          start_pos,
+                                          end_pos,
+                                          mut lines,
+                                          mut multibyte_chars,
+                                          mut non_narrow_chars,
+                                          mut normalized_pos,
+                                          name_hash,
+                                          .. } = source_file_to_import;
+
+                let source_length = (end_pos - start_pos).to_usize();
+
+                // Translate line-start positions and multibyte character
+                // position into frame of reference local to file.
+                // `SourceMap::new_imported_source_file()` will then translate those
+                // coordinates to their new global frame of reference when the
+                // offset of the SourceFile is known.
+                for pos in &mut lines {
+                    *pos = *pos - start_pos;
+                }
+                for mbc in &mut multibyte_chars {
+                    mbc.pos = mbc.pos - start_pos;
+                }
+                for swc in &mut non_narrow_chars {
+                    *swc = *swc - start_pos;
+                }
+                for np in &mut normalized_pos {
+                    np.pos = np.pos - start_pos;
+                }
+
+                let local_version = local_source_map.new_imported_source_file(name,
+                                                                       name_was_remapped,
+                                                                       self.cnum.as_u32(),
+                                                                       src_hash,
+                                                                       name_hash,
+                                                                       source_length,
+                                                                       lines,
+                                                                       multibyte_chars,
+                                                                       non_narrow_chars,
+                                                                       normalized_pos);
+                debug!("CrateMetaData::imported_source_files alloc \
+                        source_file {:?} original (start_pos {:?} end_pos {:?}) \
+                        translated (start_pos {:?} end_pos {:?})",
+                       local_version.name, start_pos, end_pos,
+                       local_version.start_pos, local_version.end_pos);
+
+                ImportedSourceFile {
+                    original_start_pos: start_pos,
+                    original_end_pos: end_pos,
+                    translated_source_file: local_version,
+                }
+            }).collect()
+        })
+    }
+
+    /// Get the `DepNodeIndex` corresponding this crate. The result of this
+    /// method is cached in the `dep_node_index` field.
+    pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
+        let mut dep_node_index = self.dep_node_index.load();
+
+        if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
+            // We have not cached the DepNodeIndex for this upstream crate yet,
+            // so use the dep-graph to find it out and cache it.
+            // Note that multiple threads can enter this block concurrently.
+            // That is fine because the DepNodeIndex remains constant
+            // throughout the whole compilation session, and multiple stores
+            // would always write the same value.
+
+            let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
+            let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
+
+            dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
+            assert!(dep_node_index != DepNodeIndex::INVALID);
+            self.dep_node_index.store(dep_node_index);
+        }
+
+        dep_node_index
+    }
+}
+
+// Cannot be implemented on 'ProcMacro', as libproc_macro
+// does not depend on libsyntax
+fn macro_kind(raw: &ProcMacro) -> MacroKind {
+    match raw {
+        ProcMacro::CustomDerive { .. } => MacroKind::Derive,
+        ProcMacro::Attr { .. } => MacroKind::Attr,
+        ProcMacro::Bang { .. } => MacroKind::Bang
+    }
+}
+
+impl<'tcx> EntryKind<'tcx> {
+    fn def_kind(&self) -> Option<DefKind> {
+        Some(match *self {
+            EntryKind::Const(..) => DefKind::Const,
+            EntryKind::AssocConst(..) => DefKind::AssocConst,
+            EntryKind::ImmStatic |
+            EntryKind::MutStatic |
+            EntryKind::ForeignImmStatic |
+            EntryKind::ForeignMutStatic => DefKind::Static,
+            EntryKind::Struct(_, _) => DefKind::Struct,
+            EntryKind::Union(_, _) => DefKind::Union,
+            EntryKind::Fn(_) |
+            EntryKind::ForeignFn(_) => DefKind::Fn,
+            EntryKind::Method(_) => DefKind::Method,
+            EntryKind::Type => DefKind::TyAlias,
+            EntryKind::TypeParam => DefKind::TyParam,
+            EntryKind::ConstParam => DefKind::ConstParam,
+            EntryKind::OpaqueTy => DefKind::OpaqueTy,
+            EntryKind::AssocType(_) => DefKind::AssocTy,
+            EntryKind::AssocOpaqueTy(_) => DefKind::AssocOpaqueTy,
+            EntryKind::Mod(_) => DefKind::Mod,
+            EntryKind::Variant(_) => DefKind::Variant,
+            EntryKind::Trait(_) => DefKind::Trait,
+            EntryKind::TraitAlias => DefKind::TraitAlias,
+            EntryKind::Enum(..) => DefKind::Enum,
+            EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
+            EntryKind::ForeignType => DefKind::ForeignTy,
+
+            EntryKind::ForeignMod |
+            EntryKind::GlobalAsm |
+            EntryKind::Impl(_) |
+            EntryKind::Field |
+            EntryKind::Generator(_) |
+            EntryKind::Closure => return None,
+        })
+    }
+}
+
 #[derive(Clone)]
 pub struct CStore {
     metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index c5954e1ea1d98..e7b2a8a88fab3 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1,27 +1,16 @@
 // Decoding metadata from a single crate's metadata
 
-use crate::cstore::{self, CrateMetadata, MetadataBlob};
+use crate::cstore::{CrateMetadata, MetadataBlob};
 use crate::schema::*;
 use crate::table::{FixedSizeEncoding, PerDefTable};
 
-use rustc_index::vec::IndexVec;
-use rustc_data_structures::sync::Lrc;
-use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
-use rustc::hir;
-use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule};
-use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
-use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
-use rustc::dep_graph::{DepNodeIndex, DepKind};
-use rustc::middle::lang_items;
 use rustc::mir::{self, interpret};
 use rustc::mir::interpret::AllocDecodingSession;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::codec::TyDecoder;
-use rustc::mir::{Body, Promoted};
 use rustc::util::captures::Captures;
 
 use std::io;
@@ -30,15 +19,9 @@ use std::num::NonZeroUsize;
 use std::u32;
 
 use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque};
-use syntax::attr;
-use syntax::ast::{self, Ident};
-use syntax::source_map::{self, respan, Spanned};
-use syntax_expand::base::{SyntaxExtensionKind, SyntaxExtension};
-use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
-use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, hygiene::MacroKind};
-use syntax_pos::symbol::{Symbol, sym};
-use log::debug;
-use proc_macro::bridge::client::ProcMacro;
+use syntax::ast::Ident;
+use syntax_pos::{self, Span, BytePos, DUMMY_SP};
+use syntax_pos::symbol::Symbol;
 
 crate struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
@@ -424,967 +407,3 @@ impl<'tcx> MetadataBlob {
         Ok(())
     }
 }
-
-impl<'tcx> EntryKind<'tcx> {
-    fn def_kind(&self) -> Option<DefKind> {
-        Some(match *self {
-            EntryKind::Const(..) => DefKind::Const,
-            EntryKind::AssocConst(..) => DefKind::AssocConst,
-            EntryKind::ImmStatic |
-            EntryKind::MutStatic |
-            EntryKind::ForeignImmStatic |
-            EntryKind::ForeignMutStatic => DefKind::Static,
-            EntryKind::Struct(_, _) => DefKind::Struct,
-            EntryKind::Union(_, _) => DefKind::Union,
-            EntryKind::Fn(_) |
-            EntryKind::ForeignFn(_) => DefKind::Fn,
-            EntryKind::Method(_) => DefKind::Method,
-            EntryKind::Type => DefKind::TyAlias,
-            EntryKind::TypeParam => DefKind::TyParam,
-            EntryKind::ConstParam => DefKind::ConstParam,
-            EntryKind::OpaqueTy => DefKind::OpaqueTy,
-            EntryKind::AssocType(_) => DefKind::AssocTy,
-            EntryKind::AssocOpaqueTy(_) => DefKind::AssocOpaqueTy,
-            EntryKind::Mod(_) => DefKind::Mod,
-            EntryKind::Variant(_) => DefKind::Variant,
-            EntryKind::Trait(_) => DefKind::Trait,
-            EntryKind::TraitAlias => DefKind::TraitAlias,
-            EntryKind::Enum(..) => DefKind::Enum,
-            EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
-            EntryKind::ForeignType => DefKind::ForeignTy,
-
-            EntryKind::ForeignMod |
-            EntryKind::GlobalAsm |
-            EntryKind::Impl(_) |
-            EntryKind::Field |
-            EntryKind::Generator(_) |
-            EntryKind::Closure => return None,
-        })
-    }
-}
-
-impl<'a, 'tcx> CrateMetadata {
-    crate fn is_proc_macro_crate(&self) -> bool {
-        self.root.proc_macro_decls_static.is_some()
-    }
-
-    fn is_proc_macro(&self, id: DefIndex) -> bool {
-        self.is_proc_macro_crate() &&
-            self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some()
-    }
-
-    fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind<'tcx>> {
-        self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self))
-    }
-
-    fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> {
-        assert!(!self.is_proc_macro(item_id));
-        self.maybe_kind(item_id).unwrap_or_else(|| {
-            bug!(
-                "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
-                item_id,
-                self.root.name,
-                self.cnum,
-            )
-        })
-    }
-
-    fn local_def_id(&self, index: DefIndex) -> DefId {
-        DefId {
-            krate: self.cnum,
-            index,
-        }
-    }
-
-    fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
-        // DefIndex's in root.proc_macro_data have a one-to-one correspondence
-        // with items in 'raw_proc_macros'.
-        // NOTE: If you update the order of macros in 'proc_macro_data' for any reason,
-        // you must also update src/libsyntax_ext/proc_macro_harness.rs
-        // Failing to do so will result in incorrect data being associated
-        // with proc macros when deserialized.
-        let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
-        &self.raw_proc_macros.unwrap()[pos]
-    }
-
-    crate fn item_name(&self, item_index: DefIndex) -> Symbol {
-        if !self.is_proc_macro(item_index) {
-            self.def_key(item_index)
-                .disambiguated_data
-                .data
-                .get_opt_name()
-                .expect("no name in item_name")
-        } else {
-            Symbol::intern(self.raw_proc_macro(item_index).name())
-        }
-    }
-
-    crate fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
-        if !self.is_proc_macro(index) {
-            self.kind(index).def_kind()
-        } else {
-            Some(DefKind::Macro(
-                macro_kind(self.raw_proc_macro(index))
-            ))
-        }
-    }
-
-    crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
-        self.root.per_def.span.get(self, index).unwrap().decode((self, sess))
-    }
-
-    crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
-        let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
-            ProcMacro::CustomDerive { trait_name, attributes, client } => {
-                let helper_attrs =
-                    attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
-                (
-                    trait_name,
-                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })),
-                    helper_attrs,
-                )
-            }
-            ProcMacro::Attr { name, client } => (
-                name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
-            ),
-            ProcMacro::Bang { name, client } => (
-                name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
-            )
-        };
-
-        SyntaxExtension::new(
-            &sess.parse_sess,
-            kind,
-            self.get_span(id, sess),
-            helper_attrs,
-            self.root.edition,
-            Symbol::intern(name),
-            &self.get_item_attrs(id, sess),
-        )
-    }
-
-    crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
-        match self.kind(item_id) {
-            EntryKind::Trait(data) => {
-                let data = data.decode((self, sess));
-                ty::TraitDef::new(self.local_def_id(item_id),
-                                  data.unsafety,
-                                  data.paren_sugar,
-                                  data.has_auto_impl,
-                                  data.is_marker,
-                                  self.def_path_table.def_path_hash(item_id))
-            },
-            EntryKind::TraitAlias => {
-                ty::TraitDef::new(self.local_def_id(item_id),
-                                  hir::Unsafety::Normal,
-                                  false,
-                                  false,
-                                  false,
-                                  self.def_path_table.def_path_hash(item_id))
-            },
-            _ => bug!("def-index does not refer to trait or trait alias"),
-        }
-    }
-
-    fn get_variant(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        kind: &EntryKind<'_>,
-        index: DefIndex,
-        parent_did: DefId,
-    ) -> ty::VariantDef {
-        let data = match kind {
-            EntryKind::Variant(data) |
-            EntryKind::Struct(data, _) |
-            EntryKind::Union(data, _) => data.decode(self),
-            _ => bug!(),
-        };
-
-        let adt_kind = match kind {
-            EntryKind::Variant(_) => ty::AdtKind::Enum,
-            EntryKind::Struct(..) => ty::AdtKind::Struct,
-            EntryKind::Union(..) => ty::AdtKind::Union,
-            _ => bug!(),
-        };
-
-        let variant_did = if adt_kind == ty::AdtKind::Enum {
-            Some(self.local_def_id(index))
-        } else {
-            None
-        };
-        let ctor_did = data.ctor.map(|index| self.local_def_id(index));
-
-        ty::VariantDef::new(
-            tcx,
-            Ident::with_dummy_span(self.item_name(index)),
-            variant_did,
-            ctor_did,
-            data.discr,
-            self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty())
-                .decode(self).map(|index| ty::FieldDef {
-                    did: self.local_def_id(index),
-                    ident: Ident::with_dummy_span(self.item_name(index)),
-                    vis: self.get_visibility(index),
-                }).collect(),
-            data.ctor_kind,
-            adt_kind,
-            parent_did,
-            false,
-        )
-    }
-
-    crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
-        let kind = self.kind(item_id);
-        let did = self.local_def_id(item_id);
-
-        let (adt_kind, repr) = match kind {
-            EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
-            EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
-            EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
-            _ => bug!("get_adt_def called on a non-ADT {:?}", did),
-        };
-
-        let variants = if let ty::AdtKind::Enum = adt_kind {
-            self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty())
-                .decode(self)
-                .map(|index| {
-                    self.get_variant(tcx, &self.kind(index), index, did)
-                })
-                .collect()
-        } else {
-            std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect()
-        };
-
-        tcx.alloc_adt_def(did, adt_kind, variants, repr)
-    }
-
-    crate fn get_predicates(
-        &self,
-        item_id: DefIndex,
-        tcx: TyCtxt<'tcx>,
-    ) -> ty::GenericPredicates<'tcx> {
-        self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx))
-    }
-
-    crate fn get_predicates_defined_on(
-        &self,
-        item_id: DefIndex,
-        tcx: TyCtxt<'tcx>,
-    ) -> ty::GenericPredicates<'tcx> {
-        self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx))
-    }
-
-    crate fn get_super_predicates(
-        &self,
-        item_id: DefIndex,
-        tcx: TyCtxt<'tcx>,
-    ) -> ty::GenericPredicates<'tcx> {
-        self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
-    }
-
-    crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
-        self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess))
-    }
-
-    crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx))
-    }
-
-    crate fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
-        match self.is_proc_macro(id) {
-            true => self.root.proc_macro_stability.clone(),
-            false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)),
-        }
-    }
-
-    crate fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
-        self.root.per_def.deprecation.get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
-            .map(|depr| depr.decode(self))
-    }
-
-    crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
-        match self.is_proc_macro(id) {
-            true => ty::Visibility::Public,
-            false => self.root.per_def.visibility.get(self, id).unwrap().decode(self),
-        }
-    }
-
-    fn get_impl_data(&self, id: DefIndex) -> ImplData {
-        match self.kind(id) {
-            EntryKind::Impl(data) => data.decode(self),
-            _ => bug!(),
-        }
-    }
-
-    crate fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
-        self.get_impl_data(id).parent_impl
-    }
-
-    crate fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
-        self.get_impl_data(id).polarity
-    }
-
-    crate fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
-        self.get_impl_data(id).defaultness
-    }
-
-    crate fn get_coerce_unsized_info(
-        &self,
-        id: DefIndex,
-    ) -> Option<ty::adjustment::CoerceUnsizedInfo> {
-        self.get_impl_data(id).coerce_unsized_info
-    }
-
-    crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
-        self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
-    }
-
-    /// Iterates over all the stability attributes in the given crate.
-    crate fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option<ast::Name>)] {
-        // FIXME: For a proc macro crate, not sure whether we should return the "host"
-        // features or an empty Vec. Both don't cause ICEs.
-        tcx.arena.alloc_from_iter(self.root
-            .lib_features
-            .decode(self))
-    }
-
-    /// Iterates over the language items in the given crate.
-    crate fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
-        if self.is_proc_macro_crate() {
-            // Proc macro crates do not export any lang-items to the target.
-            &[]
-        } else {
-            tcx.arena.alloc_from_iter(self.root
-                .lang_items
-                .decode(self)
-                .map(|(def_index, index)| (self.local_def_id(def_index), index)))
-        }
-    }
-
-    /// Iterates over the diagnostic items in the given crate.
-    crate fn get_diagnostic_items(
-        &self,
-        tcx: TyCtxt<'tcx>,
-    ) -> &'tcx FxHashMap<Symbol, DefId> {
-        tcx.arena.alloc(if self.is_proc_macro_crate() {
-            // Proc macro crates do not export any diagnostic-items to the target.
-            Default::default()
-        } else {
-            self.root
-                .diagnostic_items
-                .decode(self)
-                .map(|(name, def_index)| (name, self.local_def_id(def_index)))
-                .collect()
-        })
-    }
-
-    /// Iterates over each child of the given item.
-    crate fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
-        where F: FnMut(def::Export<hir::HirId>)
-    {
-        if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) {
-            /* If we are loading as a proc macro, we want to return the view of this crate
-             * as a proc macro crate.
-             */
-            if id == CRATE_DEF_INDEX {
-                for def_index in proc_macros_ids {
-                    let raw_macro = self.raw_proc_macro(def_index);
-                    let res = Res::Def(
-                        DefKind::Macro(macro_kind(raw_macro)),
-                        self.local_def_id(def_index),
-                    );
-                    let ident = Ident::from_str(raw_macro.name());
-                    callback(def::Export {
-                        ident: ident,
-                        res: res,
-                        vis: ty::Visibility::Public,
-                        span: DUMMY_SP,
-                    });
-                }
-            }
-            return
-        }
-
-        // Find the item.
-        let kind = match self.maybe_kind(id) {
-            None => return,
-            Some(kind) => kind,
-        };
-
-        // Iterate over all children.
-        let macros_only = self.dep_kind.lock().macros_only();
-        let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty());
-        for child_index in children.decode((self, sess)) {
-            if macros_only {
-                continue
-            }
-
-            // Get the item.
-            if let Some(child_kind) = self.maybe_kind(child_index) {
-                match child_kind {
-                    EntryKind::MacroDef(..) => {}
-                    _ if macros_only => continue,
-                    _ => {}
-                }
-
-                // Hand off the item to the callback.
-                match child_kind {
-                    // FIXME(eddyb) Don't encode these in children.
-                    EntryKind::ForeignMod => {
-                        let child_children =
-                            self.root.per_def.children.get(self, child_index)
-                                .unwrap_or(Lazy::empty());
-                        for child_index in child_children.decode((self, sess)) {
-                            if let Some(kind) = self.def_kind(child_index) {
-                                callback(def::Export {
-                                    res: Res::Def(kind, self.local_def_id(child_index)),
-                                    ident: Ident::with_dummy_span(self.item_name(child_index)),
-                                    vis: self.get_visibility(child_index),
-                                    span: self.root.per_def.span.get(self, child_index).unwrap()
-                                        .decode((self, sess)),
-                                });
-                            }
-                        }
-                        continue;
-                    }
-                    EntryKind::Impl(_) => continue,
-
-                    _ => {}
-                }
-
-                let def_key = self.def_key(child_index);
-                let span = self.get_span(child_index, sess);
-                if let (Some(kind), Some(name)) =
-                    (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::with_dummy_span(name);
-                    let vis = self.get_visibility(child_index);
-                    let def_id = self.local_def_id(child_index);
-                    let res = Res::Def(kind, def_id);
-                    callback(def::Export { res, ident, vis, span });
-                    // For non-re-export structs and variants add their constructors to children.
-                    // Re-export lists automatically contain constructors when necessary.
-                    match kind {
-                        DefKind::Struct => {
-                            if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) {
-                                let ctor_kind = self.get_ctor_kind(child_index);
-                                let ctor_res = Res::Def(
-                                    DefKind::Ctor(CtorOf::Struct, ctor_kind),
-                                    ctor_def_id,
-                                );
-                                let vis = self.get_visibility(ctor_def_id.index);
-                                callback(def::Export { res: ctor_res, vis, ident, span });
-                            }
-                        }
-                        DefKind::Variant => {
-                            // Braced variants, unlike structs, generate unusable names in
-                            // value namespace, they are reserved for possible future use.
-                            // It's ok to use the variant's id as a ctor id since an
-                            // error will be reported on any use of such resolution anyway.
-                            let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
-                            let ctor_kind = self.get_ctor_kind(child_index);
-                            let ctor_res = Res::Def(
-                                DefKind::Ctor(CtorOf::Variant, ctor_kind),
-                                ctor_def_id,
-                            );
-                            let mut vis = self.get_visibility(ctor_def_id.index);
-                            if ctor_def_id == def_id && vis == ty::Visibility::Public {
-                                // For non-exhaustive variants lower the constructor visibility to
-                                // within the crate. We only need this for fictive constructors,
-                                // for other constructors correct visibilities
-                                // were already encoded in metadata.
-                                let attrs = self.get_item_attrs(def_id.index, sess);
-                                if attr::contains_name(&attrs, sym::non_exhaustive) {
-                                    let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
-                                    vis = ty::Visibility::Restricted(crate_def_id);
-                                }
-                            }
-                            callback(def::Export { res: ctor_res, ident, vis, span });
-                        }
-                        _ => {}
-                    }
-                }
-            }
-        }
-
-        if let EntryKind::Mod(data) = kind {
-            for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
-                match exp.res {
-                    Res::Def(DefKind::Macro(..), _) => {}
-                    _ if macros_only => continue,
-                    _ => {}
-                }
-                callback(exp);
-            }
-        }
-    }
-
-    crate fn is_item_mir_available(&self, id: DefIndex) -> bool {
-        !self.is_proc_macro(id) &&
-            self.root.per_def.mir.get(self, id).is_some()
-    }
-
-    crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
-        self.root.per_def.mir.get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
-            .unwrap_or_else(|| {
-                bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id))
-            })
-            .decode((self, tcx))
-    }
-
-    crate fn get_promoted_mir(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        id: DefIndex,
-    ) -> IndexVec<Promoted, Body<'tcx>> {
-        self.root.per_def.promoted_mir.get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
-            .unwrap_or_else(|| {
-                bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id))
-            })
-            .decode((self, tcx))
-    }
-
-    crate fn mir_const_qualif(&self, id: DefIndex) -> u8 {
-        match self.kind(id) {
-            EntryKind::Const(qualif, _) |
-            EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) |
-            EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => {
-                qualif.mir
-            }
-            _ => bug!(),
-        }
-    }
-
-    crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
-        let def_key = self.def_key(id);
-        let parent = self.local_def_id(def_key.parent.unwrap());
-        let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
-
-        let (kind, container, has_self) = match self.kind(id) {
-            EntryKind::AssocConst(container, _, _) => {
-                (ty::AssocKind::Const, container, false)
-            }
-            EntryKind::Method(data) => {
-                let data = data.decode(self);
-                (ty::AssocKind::Method, data.container, data.has_self)
-            }
-            EntryKind::AssocType(container) => {
-                (ty::AssocKind::Type, container, false)
-            }
-            EntryKind::AssocOpaqueTy(container) => {
-                (ty::AssocKind::OpaqueTy, container, false)
-            }
-            _ => bug!("cannot get associated-item of `{:?}`", def_key)
-        };
-
-        ty::AssocItem {
-            ident: Ident::with_dummy_span(name),
-            kind,
-            vis: self.get_visibility(id),
-            defaultness: container.defaultness(),
-            def_id: self.local_def_id(id),
-            container: container.with_def_id(parent),
-            method_has_self_argument: has_self
-        }
-    }
-
-    crate fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
-        self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty())
-            .decode(self).collect()
-    }
-
-    crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
-        match self.kind(node_id) {
-            EntryKind::Struct(data, _) |
-            EntryKind::Union(data, _) |
-            EntryKind::Variant(data) => data.decode(self).ctor_kind,
-            _ => CtorKind::Fictive,
-        }
-    }
-
-    crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
-        match self.kind(node_id) {
-            EntryKind::Struct(data, _) => {
-                data.decode(self).ctor.map(|index| self.local_def_id(index))
-            }
-            EntryKind::Variant(data) => {
-                data.decode(self).ctor.map(|index| self.local_def_id(index))
-            }
-            _ => None,
-        }
-    }
-
-    crate fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
-        // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
-        // we assume that someone passing in a tuple struct ctor is actually wanting to
-        // look at the definition
-        let def_key = self.def_key(node_id);
-        let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor {
-            def_key.parent.unwrap()
-        } else {
-            node_id
-        };
-
-        Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty())
-            .decode((self, sess))
-            .collect::<Vec<_>>())
-    }
-
-    crate fn get_struct_field_names(
-        &self,
-        id: DefIndex,
-        sess: &Session,
-    ) -> Vec<Spanned<ast::Name>> {
-        self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty())
-            .decode(self)
-            .map(|index| respan(self.get_span(index, sess), self.item_name(index)))
-            .collect()
-    }
-
-    // Translate a DefId from the current compilation environment to a DefId
-    // for an external crate.
-    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
-        for (local, &global) in self.cnum_map.iter_enumerated() {
-            if global == did.krate {
-                return Some(DefId {
-                    krate: local,
-                    index: did.index,
-                });
-            }
-        }
-
-        None
-    }
-
-    crate fn get_inherent_implementations_for_type(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        id: DefIndex,
-    ) -> &'tcx [DefId] {
-        tcx.arena.alloc_from_iter(
-            self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty())
-                .decode(self)
-                .map(|index| self.local_def_id(index))
-        )
-    }
-
-    crate fn get_implementations_for_trait(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        filter: Option<DefId>,
-    ) -> &'tcx [DefId] {
-        if self.is_proc_macro_crate() {
-            // proc-macro crates export no trait impls.
-            return &[]
-        }
-
-        // Do a reverse lookup beforehand to avoid touching the crate_num
-        // hash map in the loop below.
-        let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
-            Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
-            Some(None) => return &[],
-            None => None,
-        };
-
-        if let Some(filter) = filter {
-            if let Some(impls) = self.trait_impls.get(&filter) {
-                tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
-            } else {
-                &[]
-            }
-        } else {
-            tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| {
-                impls.decode(self).map(|idx| self.local_def_id(idx))
-            }))
-        }
-    }
-
-    crate fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
-        let def_key = self.def_key(id);
-        match def_key.disambiguated_data.data {
-            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
-            // Not an associated item
-            _ => return None,
-        }
-        def_key.parent.and_then(|parent_index| {
-            match self.kind(parent_index) {
-                EntryKind::Trait(_) |
-                EntryKind::TraitAlias => Some(self.local_def_id(parent_index)),
-                _ => None,
-            }
-        })
-    }
-
-
-    crate fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
-        if self.is_proc_macro_crate() {
-            // Proc macro crates do not have any *target* native libraries.
-            vec![]
-        } else {
-            self.root.native_libraries.decode((self, sess)).collect()
-        }
-    }
-
-    crate fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
-        if self.is_proc_macro_crate() {
-            // Proc macro crates do not have any *target* foreign modules.
-            &[]
-        } else {
-            tcx.arena.alloc_from_iter(self.root.foreign_modules.decode((self, tcx.sess)))
-        }
-    }
-
-    crate fn get_dylib_dependency_formats(
-        &self,
-        tcx: TyCtxt<'tcx>,
-    ) -> &'tcx [(CrateNum, LinkagePreference)] {
-        tcx.arena.alloc_from_iter(self.root
-            .dylib_dependency_formats
-            .decode(self)
-            .enumerate()
-            .flat_map(|(i, link)| {
-                let cnum = CrateNum::new(i + 1);
-                link.map(|link| (self.cnum_map[cnum], link))
-            }))
-    }
-
-    crate fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
-        if self.is_proc_macro_crate() {
-            // Proc macro crates do not depend on any target weak lang-items.
-            &[]
-        } else {
-            tcx.arena.alloc_from_iter(self.root
-                .lang_items_missing
-                .decode(self))
-        }
-    }
-
-    crate fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
-        let param_names = match self.kind(id) {
-            EntryKind::Fn(data) |
-            EntryKind::ForeignFn(data) => data.decode(self).param_names,
-            EntryKind::Method(data) => data.decode(self).fn_data.param_names,
-            _ => Lazy::empty(),
-        };
-        param_names.decode(self).collect()
-    }
-
-    crate fn exported_symbols(
-        &self,
-        tcx: TyCtxt<'tcx>,
-    ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
-        if self.is_proc_macro_crate() {
-            // If this crate is a custom derive crate, then we're not even going to
-            // link those in so we skip those crates.
-            vec![]
-        } else {
-            self.root.exported_symbols.decode((self, tcx)).collect()
-        }
-    }
-
-    crate fn get_rendered_const(&self, id: DefIndex) -> String {
-        match self.kind(id) {
-            EntryKind::Const(_, data) |
-            EntryKind::AssocConst(_, _, data) => data.decode(self).0,
-            _ => bug!(),
-        }
-    }
-
-    crate fn get_macro(&self, id: DefIndex) -> MacroDef {
-        match self.kind(id) {
-            EntryKind::MacroDef(macro_def) => macro_def.decode(self),
-            _ => bug!(),
-        }
-    }
-
-    crate fn is_const_fn_raw(&self, id: DefIndex) -> bool {
-        let constness = match self.kind(id) {
-            EntryKind::Method(data) => data.decode(self).fn_data.constness,
-            EntryKind::Fn(data) => data.decode(self).constness,
-            EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const,
-            _ => hir::Constness::NotConst,
-        };
-        constness == hir::Constness::Const
-    }
-
-    crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
-         match self.kind(id) {
-            EntryKind::Fn(data) => data.decode(self).asyncness,
-            EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
-            EntryKind::ForeignFn(data) => data.decode(self).asyncness,
-            _ => bug!("asyncness: expected function kind"),
-        }
-    }
-
-    crate fn is_foreign_item(&self, id: DefIndex) -> bool {
-        match self.kind(id) {
-            EntryKind::ForeignImmStatic |
-            EntryKind::ForeignMutStatic |
-            EntryKind::ForeignFn(_) => true,
-            _ => false,
-        }
-    }
-
-    crate fn static_mutability(&self, id: DefIndex) -> Option<hir::Mutability> {
-        match self.kind(id) {
-            EntryKind::ImmStatic |
-            EntryKind::ForeignImmStatic => Some(hir::MutImmutable),
-            EntryKind::MutStatic |
-            EntryKind::ForeignMutStatic => Some(hir::MutMutable),
-            _ => None,
-        }
-    }
-
-    crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
-        self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx))
-    }
-
-    #[inline]
-    crate fn def_key(&self, index: DefIndex) -> DefKey {
-        let mut key = self.def_path_table.def_key(index);
-        if self.is_proc_macro(index) {
-            let name = self.raw_proc_macro(index).name();
-            key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
-        }
-        key
-    }
-
-    // Returns the path leading to the thing with this `id`.
-    crate fn def_path(&self, id: DefIndex) -> DefPath {
-        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
-        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
-    }
-
-    #[inline]
-    crate fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.def_path_table.def_path_hash(index)
-    }
-
-    /// Imports the source_map from an external crate into the source_map of the crate
-    /// currently being compiled (the "local crate").
-    ///
-    /// The import algorithm works analogous to how AST items are inlined from an
-    /// external crate's metadata:
-    /// For every SourceFile in the external source_map an 'inline' copy is created in the
-    /// local source_map. The correspondence relation between external and local
-    /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this
-    /// function. When an item from an external crate is later inlined into this
-    /// crate, this correspondence information is used to translate the span
-    /// information of the inlined item so that it refers the correct positions in
-    /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
-    ///
-    /// The import algorithm in the function below will reuse SourceFiles already
-    /// existing in the local source_map. For example, even if the SourceFile of some
-    /// source file of libstd gets imported many times, there will only ever be
-    /// one SourceFile object for the corresponding file in the local source_map.
-    ///
-    /// Note that imported SourceFiles do not actually contain the source code of the
-    /// file they represent, just information about length, line breaks, and
-    /// multibyte characters. This information is enough to generate valid debuginfo
-    /// for items inlined from other crates.
-    ///
-    /// Proc macro crates don't currently export spans, so this function does not have
-    /// to work for them.
-    fn imported_source_files(
-        &'a self,
-        local_source_map: &source_map::SourceMap,
-    ) -> &[cstore::ImportedSourceFile] {
-        self.source_map_import_info.init_locking(|| {
-            let external_source_map = self.root.source_map.decode(self);
-
-            external_source_map.map(|source_file_to_import| {
-                // We can't reuse an existing SourceFile, so allocate a new one
-                // containing the information we need.
-                let syntax_pos::SourceFile { name,
-                                          name_was_remapped,
-                                          src_hash,
-                                          start_pos,
-                                          end_pos,
-                                          mut lines,
-                                          mut multibyte_chars,
-                                          mut non_narrow_chars,
-                                          mut normalized_pos,
-                                          name_hash,
-                                          .. } = source_file_to_import;
-
-                let source_length = (end_pos - start_pos).to_usize();
-
-                // Translate line-start positions and multibyte character
-                // position into frame of reference local to file.
-                // `SourceMap::new_imported_source_file()` will then translate those
-                // coordinates to their new global frame of reference when the
-                // offset of the SourceFile is known.
-                for pos in &mut lines {
-                    *pos = *pos - start_pos;
-                }
-                for mbc in &mut multibyte_chars {
-                    mbc.pos = mbc.pos - start_pos;
-                }
-                for swc in &mut non_narrow_chars {
-                    *swc = *swc - start_pos;
-                }
-                for np in &mut normalized_pos {
-                    np.pos = np.pos - start_pos;
-                }
-
-                let local_version = local_source_map.new_imported_source_file(name,
-                                                                       name_was_remapped,
-                                                                       self.cnum.as_u32(),
-                                                                       src_hash,
-                                                                       name_hash,
-                                                                       source_length,
-                                                                       lines,
-                                                                       multibyte_chars,
-                                                                       non_narrow_chars,
-                                                                       normalized_pos);
-                debug!("CrateMetaData::imported_source_files alloc \
-                        source_file {:?} original (start_pos {:?} end_pos {:?}) \
-                        translated (start_pos {:?} end_pos {:?})",
-                       local_version.name, start_pos, end_pos,
-                       local_version.start_pos, local_version.end_pos);
-
-                cstore::ImportedSourceFile {
-                    original_start_pos: start_pos,
-                    original_end_pos: end_pos,
-                    translated_source_file: local_version,
-                }
-            }).collect()
-        })
-    }
-
-    /// Get the `DepNodeIndex` corresponding this crate. The result of this
-    /// method is cached in the `dep_node_index` field.
-    pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
-        let mut dep_node_index = self.dep_node_index.load();
-
-        if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
-            // We have not cached the DepNodeIndex for this upstream crate yet,
-            // so use the dep-graph to find it out and cache it.
-            // Note that multiple threads can enter this block concurrently.
-            // That is fine because the DepNodeIndex remains constant
-            // throughout the whole compilation session, and multiple stores
-            // would always write the same value.
-
-            let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
-            let dep_node = def_path_hash.to_dep_node(DepKind::CrateMetadata);
-
-            dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
-            assert!(dep_node_index != DepNodeIndex::INVALID);
-            self.dep_node_index.store(dep_node_index);
-        }
-
-        dep_node_index
-    }
-}
-
-// Cannot be implemented on 'ProcMacro', as libproc_macro
-// does not depend on libsyntax
-fn macro_kind(raw: &ProcMacro) -> MacroKind {
-    match raw {
-        ProcMacro::CustomDerive { .. } => MacroKind::Derive,
-        ProcMacro::Attr { .. } => MacroKind::Attr,
-        ProcMacro::Bang { .. } => MacroKind::Bang
-    }
-}

From 147d03c8ac947797bfc35245f45af9d7ea982625 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 31 Oct 2019 12:34:25 -0300
Subject: [PATCH 2/5] Make fields with sync types on CrateMetadata private

---
 src/librustc_metadata/creader.rs | 20 ++++++----------
 src/librustc_metadata/cstore.rs  | 39 ++++++++++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 07c49d91797d4..ac3c036ad35d1 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -3,13 +3,10 @@
 use crate::cstore::{self, CStore, MetadataBlob};
 use crate::locator::{self, CratePaths};
 use crate::schema::{CrateRoot, CrateDep};
-use rustc_data_structures::sync::{Lock, Once, AtomicCell};
 
 use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::svh::Svh;
-use rustc::dep_graph::DepNodeIndex;
 use rustc::middle::cstore::DepKind;
-use rustc::mir::interpret::AllocDecodingState;
 use rustc::session::{Session, CrateDisambiguator};
 use rustc::session::config::{Sanitizer, self};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
@@ -241,24 +238,21 @@ impl<'a> CrateLoader<'a> {
             crate_root.def_path_table.decode((&metadata, self.sess))
         });
 
-        self.cstore.set_crate_data(cnum, cstore::CrateMetadata {
-            extern_crate: Lock::new(None),
+        self.cstore.set_crate_data(cnum, cstore::CrateMetadata::new(
             def_path_table,
             trait_impls,
-            root: crate_root,
+            crate_root,
             host_hash,
-            blob: metadata,
+            metadata,
             cnum_map,
             cnum,
-            dependencies: Lock::new(dependencies),
-            source_map_import_info: Once::new(),
-            alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index),
-            dep_kind: Lock::new(dep_kind),
+            dependencies,
+            interpret_alloc_index,
+            dep_kind,
             source,
             private_dep,
             raw_proc_macros,
-            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
-        });
+        ));
 
         cnum
     }
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 459350ad074d3..49b9eda7c6436 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -77,14 +77,14 @@ crate struct CrateMetadata {
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     crate raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
-    crate source_map_import_info: Once<Vec<ImportedSourceFile>>,
+    source_map_import_info: Once<Vec<ImportedSourceFile>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     crate alloc_decoding_state: AllocDecodingState,
     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
     /// It is initialized on the first access in `get_crate_dep_node_index()`.
     /// Do not access the value directly, as it might not have been initialized yet.
     /// The field must always be initialized to `DepNodeIndex::INVALID`.
-    crate dep_node_index: AtomicCell<DepNodeIndex>,
+    dep_node_index: AtomicCell<DepNodeIndex>,
 
     // --- Other significant crate properties ---
 
@@ -113,6 +113,41 @@ crate struct CrateMetadata {
 }
 
 impl<'a, 'tcx> CrateMetadata {
+    crate fn new(
+        def_path_table: DefPathTable,
+        trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>,
+        root: schema::CrateRoot<'static>,
+        host_hash: Option<Svh>,
+        blob: MetadataBlob,
+        cnum_map: CrateNumMap,
+        cnum: CrateNum,
+        dependencies: Vec<CrateNum>,
+        interpret_alloc_index: Vec<u32>,
+        dep_kind: DepKind,
+        source: CrateSource,
+        private_dep: bool,
+        raw_proc_macros: Option<&'static [ProcMacro]>,
+    ) -> Self {
+        Self {
+            extern_crate: Lock::new(None),
+            def_path_table,
+            trait_impls,
+            root,
+            host_hash,
+            blob,
+            cnum_map,
+            cnum,
+            dependencies: Lock::new(dependencies),
+            source_map_import_info: Once::new(),
+            alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index),
+            dep_kind: Lock::new(dep_kind),
+            source,
+            private_dep,
+            raw_proc_macros,
+            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
+        }
+    }
+
     crate fn is_proc_macro_crate(&self) -> bool {
         self.root.proc_macro_decls_static.is_some()
     }

From 69a021f816b9efa1de07dbcfd5998558e69a1435 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 1 Nov 2019 17:26:37 -0300
Subject: [PATCH 3/5] Make CrateMetadata dep_kind private

---
 src/librustc_metadata/creader.rs     |  8 +++-----
 src/librustc_metadata/cstore.rs      | 20 +++++++++++++++++++-
 src/librustc_metadata/cstore_impl.rs | 10 +++-------
 3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index ac3c036ad35d1..190ed104cc5fc 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -49,7 +49,7 @@ fn dump_crates(cstore: &CStore) {
         info!("  name: {}", data.root.name);
         info!("  cnum: {}", data.cnum);
         info!("  hash: {}", data.root.hash);
-        info!("  reqd: {:?}", *data.dep_kind.lock());
+        info!("  reqd: {:?}", data.get_dep_kind());
         let CrateSource { dylib, rlib, rmeta } = data.source.clone();
         dylib.map(|dl| info!("  dylib: {}", dl.0.display()));
         rlib.map(|rl|  info!("   rlib: {}", rl.0.display()));
@@ -375,9 +375,7 @@ impl<'a> CrateLoader<'a> {
                 if data.root.proc_macro_data.is_some() {
                     dep_kind = DepKind::UnexportedMacrosOnly;
                 }
-                data.dep_kind.with_lock(|data_dep_kind| {
-                    *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
-                });
+                data.set_max_dep_kind(dep_kind);
                 Ok(cnum)
             }
             (LoadResult::Loaded(library), host_library) => {
@@ -549,7 +547,7 @@ impl<'a> CrateLoader<'a> {
                 // #![panic_runtime] crate.
                 self.inject_dependency_if(cnum, "a panic runtime",
                                           &|data| data.root.needs_panic_runtime);
-                runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
+                runtime_found = runtime_found || data.get_dep_kind() == DepKind::Explicit;
             }
         });
 
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 49b9eda7c6436..0d52084b17f25 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -30,6 +30,7 @@ use syntax_expand::base::{SyntaxExtensionKind, SyntaxExtension};
 use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
 use syntax_pos::{self, Span, Pos, DUMMY_SP, hygiene::MacroKind};
 use syntax_pos::symbol::{Symbol, sym};
+use std::cmp;
 
 pub use crate::cstore_impl::{provide, provide_extern};
 
@@ -96,7 +97,7 @@ crate struct CrateMetadata {
     /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
     crate dependencies: Lock<Vec<CrateNum>>,
     /// How to link (or not link) this crate to the currently compiled crate.
-    crate dep_kind: Lock<DepKind>,
+    dep_kind: Lock<DepKind>,
     /// Filesystem location of this crate.
     crate source: CrateSource,
     /// Whether or not this crate should be consider a private dependency
@@ -446,6 +447,23 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
+    crate fn get_dep_kind(&self) -> DepKind {
+        *self.dep_kind.lock()
+    }
+
+    crate fn export_macros_untracked(&self) {
+        let mut dep_kind = self.dep_kind.lock();
+        if *dep_kind == DepKind::UnexportedMacrosOnly {
+            *dep_kind = DepKind::MacrosOnly;
+        }
+    }
+
+    crate fn set_max_dep_kind(&self, dep_kind: DepKind) {
+        self.dep_kind.with_lock(|data_dep_kind| {
+            *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
+        });
+    }
+
     /// Iterates over the diagnostic items in the given crate.
     crate fn get_diagnostic_items(
         &self,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 2e6ed1d187a68..0325fecbcd182 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -6,7 +6,7 @@ use crate::foreign_modules;
 use crate::schema;
 
 use rustc::ty::query::QueryConfig;
-use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind};
+use rustc::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
 use rustc::middle::dependency_format::Linkage;
@@ -210,8 +210,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
 
     visibility => { cdata.get_visibility(def_id.index) }
     dep_kind => {
-        let r = *cdata.dep_kind.lock();
-        r
+        cdata.get_dep_kind()
     }
     crate_name => { cdata.root.name }
     item_children => {
@@ -404,10 +403,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 impl cstore::CStore {
     pub fn export_macros_untracked(&self, cnum: CrateNum) {
         let data = self.get_crate_data(cnum);
-        let mut dep_kind = data.dep_kind.lock();
-        if *dep_kind == DepKind::UnexportedMacrosOnly {
-            *dep_kind = DepKind::MacrosOnly;
-        }
+        data.export_macros_untracked();
     }
 
     pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> {

From 6f9bfda0793f1ec290aba27db708cc3fd63e2818 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 1 Nov 2019 18:07:45 -0300
Subject: [PATCH 4/5] update_extern_crate belongs to CrateMetadata

This also allows us to make extern_crate field private
---
 src/librustc_metadata/creader.rs     | 53 ++++---------------------
 src/librustc_metadata/cstore.rs      | 59 +++++++++++++++++++++++++++-
 src/librustc_metadata/cstore_impl.rs | 13 +-----
 3 files changed, 67 insertions(+), 58 deletions(-)

diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 190ed104cc5fc..6d6fa57d27702 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -18,7 +18,7 @@ use rustc::hir::map::Definitions;
 use rustc::hir::def_id::LOCAL_CRATE;
 
 use std::path::Path;
-use std::{cmp, fs};
+use std::fs;
 
 use syntax::ast;
 use syntax::attr;
@@ -412,47 +412,6 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn update_extern_crate(&self,
-                           cnum: CrateNum,
-                           mut extern_crate: ExternCrate,
-                           visited: &mut FxHashSet<(CrateNum, bool)>)
-    {
-        if !visited.insert((cnum, extern_crate.is_direct())) { return }
-
-        let cmeta = self.cstore.get_crate_data(cnum);
-        let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
-
-        // Prefer:
-        // - something over nothing (tuple.0);
-        // - direct extern crate to indirect (tuple.1);
-        // - shorter paths to longer (tuple.2).
-        let new_rank = (
-            true,
-            extern_crate.is_direct(),
-            cmp::Reverse(extern_crate.path_len),
-        );
-        let old_rank = match *old_extern_crate {
-            None => (false, false, cmp::Reverse(usize::max_value())),
-            Some(ref c) => (
-                true,
-                c.is_direct(),
-                cmp::Reverse(c.path_len),
-            ),
-        };
-        if old_rank >= new_rank {
-            return; // no change needed
-        }
-
-        *old_extern_crate = Some(extern_crate);
-        drop(old_extern_crate);
-
-        // Propagate the extern crate info to dependencies.
-        extern_crate.dependency_of = cnum;
-        for &dep_cnum in cmeta.dependencies.borrow().iter() {
-            self.update_extern_crate(dep_cnum, extern_crate, visited);
-        }
-    }
-
     // Go through the crate metadata and load any crates that it references
     fn resolve_crate_deps(&mut self,
                           root: &CratePaths,
@@ -889,7 +848,9 @@ impl<'a> CrateLoader<'a> {
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
                 let path_len = definitions.def_path(def_id.index).data.len();
-                self.update_extern_crate(
+
+                let cmeta = self.cstore.get_crate_data(cnum);
+                cmeta.update_extern_crate(
                     cnum,
                     ExternCrate {
                         src: ExternCrateSource::Extern(def_id),
@@ -908,7 +869,8 @@ impl<'a> CrateLoader<'a> {
     pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
         let cnum = self.resolve_crate(name, span, DepKind::Explicit, None);
 
-        self.update_extern_crate(
+        let cmeta = self.cstore.get_crate_data(cnum);
+        cmeta.update_extern_crate(
             cnum,
             ExternCrate {
                 src: ExternCrateSource::Path,
@@ -926,7 +888,8 @@ impl<'a> CrateLoader<'a> {
     pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
         let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?;
 
-        self.update_extern_crate(
+        let cmeta = self.cstore.get_crate_data(cnum);
+        cmeta.update_extern_crate(
             cnum,
             ExternCrate {
                 src: ExternCrateSource::Path,
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 0d52084b17f25..15ceeb09fc86d 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -16,7 +16,7 @@ use rustc::middle::cstore::{
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::mir::{Body, Promoted};
 use rustc::mir::interpret::AllocDecodingState;
-use rustc::util::nodemap::FxHashMap;
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::{Lrc, Lock, MetadataRef, Once, AtomicCell};
@@ -110,7 +110,7 @@ crate struct CrateMetadata {
 
     /// Information about the `extern crate` item or path that caused this crate to be loaded.
     /// If this is `None`, then the crate was injected (e.g., by the allocator).
-    crate extern_crate: Lock<Option<ExternCrate>>,
+    extern_crate: Lock<Option<ExternCrate>>,
 }
 
 impl<'a, 'tcx> CrateMetadata {
@@ -464,6 +464,61 @@ impl<'a, 'tcx> CrateMetadata {
         });
     }
 
+    crate fn get_extern_crate_arenas(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ExternCrate> {
+        let r = *self.extern_crate.lock();
+        r.map(|c| &*tcx.arena.alloc(c))
+    }
+
+    crate fn is_extern_crate_direct(&self) -> bool {
+        match *self.extern_crate.borrow() {
+            Some(extern_crate) if !extern_crate.is_direct() => true,
+            _ => false,
+        }
+    }
+
+    // let cmeta = self.cstore.get_crate_data(cnum);
+    crate fn update_extern_crate(
+        &self,
+        cnum: CrateNum,
+        mut extern_crate: ExternCrate,
+        visited: &mut FxHashSet<(CrateNum, bool)>,
+    ) {
+        if !visited.insert((cnum, extern_crate.is_direct())) { return }
+
+        let mut old_extern_crate = self.extern_crate.borrow_mut();
+
+        // Prefer:
+        // - something over nothing (tuple.0);
+        // - direct extern crate to indirect (tuple.1);
+        // - shorter paths to longer (tuple.2).
+        let new_rank = (
+            true,
+            extern_crate.is_direct(),
+            cmp::Reverse(extern_crate.path_len),
+        );
+        let old_rank = match *old_extern_crate {
+            None => (false, false, cmp::Reverse(usize::max_value())),
+            Some(ref c) => (
+                true,
+                c.is_direct(),
+                cmp::Reverse(c.path_len),
+            ),
+        };
+        if old_rank >= new_rank {
+            return; // no change needed
+        }
+
+        *old_extern_crate = Some(extern_crate);
+        drop(old_extern_crate);
+
+        // Propagate the extern crate info to dependencies.
+        extern_crate.dependency_of = cnum;
+        for &dep_cnum in self.dependencies.borrow().iter() {
+            self.update_extern_crate(dep_cnum, extern_crate, visited);
+        }
+    }
+
+
     /// Iterates over the diagnostic items in the given crate.
     crate fn get_diagnostic_items(
         &self,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 0325fecbcd182..1228c5034dba5 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -160,10 +160,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
-    extern_crate => {
-        let r = *cdata.extern_crate.lock();
-        r.map(|c| &*tcx.arena.alloc(c))
-    }
+    extern_crate => { cdata.get_extern_crate_arenas(tcx) }
     is_no_builtins => { cdata.root.no_builtins }
     symbol_mangling_version => { cdata.root.symbol_mangling_version }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
@@ -223,13 +220,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     diagnostic_items => { cdata.get_diagnostic_items(tcx) }
     missing_lang_items => { cdata.get_missing_lang_items(tcx) }
 
-    missing_extern_crate_item => {
-        let r = match *cdata.extern_crate.borrow() {
-            Some(extern_crate) if !extern_crate.is_direct() => true,
-            _ => false,
-        };
-        r
-    }
+    missing_extern_crate_item => { cdata.is_extern_crate_direct() }
 
     used_crate_source => { Lrc::new(cdata.source.clone()) }
 

From f86fefac1239f14fe458dfc90a6689375fcd430b Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 1 Nov 2019 18:11:08 -0300
Subject: [PATCH 5/5] Make CrateMetadata dependencies private

---
 src/librustc_metadata/creader.rs | 2 +-
 src/librustc_metadata/cstore.rs  | 6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 6d6fa57d27702..ffde8036f787b 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -806,7 +806,7 @@ impl<'a> CrateLoader<'a> {
             }
 
             info!("injecting a dep from {} to {}", cnum, krate);
-            data.dependencies.borrow_mut().push(krate);
+            data.push_dependency(krate);
         });
     }
 
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 15ceeb09fc86d..361417c58fafa 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -95,7 +95,7 @@ crate struct CrateMetadata {
     /// IDs as they are seen from the current compilation session.
     crate cnum_map: CrateNumMap,
     /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
-    crate dependencies: Lock<Vec<CrateNum>>,
+    dependencies: Lock<Vec<CrateNum>>,
     /// How to link (or not link) this crate to the currently compiled crate.
     dep_kind: Lock<DepKind>,
     /// Filesystem location of this crate.
@@ -1134,6 +1134,10 @@ impl<'a, 'tcx> CrateMetadata {
 
         dep_node_index
     }
+
+    crate fn push_dependency(&self, krate: CrateNum) {
+        self.dependencies.borrow_mut().push(krate);
+    }
 }
 
 // Cannot be implemented on 'ProcMacro', as libproc_macro