]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_metadata/src/rmeta/decoder.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / compiler / rustc_metadata / src / rmeta / decoder.rs
index 746c3b6af12f017d04e6740acc23f491163f67f7..43f7b2a992838746c54e886e741fb175470d1f4c 100644 (file)
@@ -77,6 +77,10 @@ crate struct CrateMetadata {
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
     source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
+    /// For every definition in this crate, maps its `DefPathHash` to its
+    /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
+    /// this is used.
+    def_path_hash_map: OnceCell<FxHashMap<DefPathHash, DefIndex>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     alloc_decoding_state: AllocDecodingState,
     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
@@ -644,6 +648,7 @@ impl EntryKind {
             EntryKind::TraitAlias => DefKind::TraitAlias,
             EntryKind::Enum(..) => DefKind::Enum,
             EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
+            EntryKind::ProcMacro(kind) => DefKind::Macro(kind),
             EntryKind::ForeignType => DefKind::ForeignTy,
             EntryKind::Impl(_) => DefKind::Impl,
             EntryKind::Closure => DefKind::Closure,
@@ -685,20 +690,11 @@ impl CrateRoot<'_> {
 }
 
 impl<'a, 'tcx> CrateMetadataRef<'a> {
-    fn is_proc_macro(&self, id: DefIndex) -> bool {
-        self.root
-            .proc_macro_data
-            .as_ref()
-            .and_then(|data| data.macros.decode(self).find(|x| *x == id))
-            .is_some()
-    }
-
     fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
         self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
     }
 
     fn kind(&self, item_id: DefIndex) -> EntryKind {
-        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 {}",
@@ -725,35 +721,24 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
-        if !self.is_proc_macro(item_index) {
-            let name = self
-                .def_key(item_index)
-                .disambiguated_data
-                .data
-                .get_opt_name()
-                .expect("no name in item_ident");
-            let span = self
-                .root
-                .tables
-                .ident_span
-                .get(self, item_index)
-                .map(|data| data.decode((self, sess)))
-                .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
-            Ident::new(name, span)
-        } else {
-            Ident::new(
-                Symbol::intern(self.raw_proc_macro(item_index).name()),
-                self.get_span(item_index, sess),
-            )
-        }
+        let name = self
+            .def_key(item_index)
+            .disambiguated_data
+            .data
+            .get_opt_name()
+            .expect("no name in item_ident");
+        let span = self
+            .root
+            .tables
+            .ident_span
+            .get(self, item_index)
+            .map(|data| data.decode((self, sess)))
+            .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
+        Ident::new(name, span)
     }
 
     fn def_kind(&self, index: DefIndex) -> DefKind {
-        if !self.is_proc_macro(index) {
-            self.kind(index).def_kind()
-        } else {
-            DefKind::Macro(macro_kind(self.raw_proc_macro(index)))
-        }
+        self.kind(index).def_kind()
     }
 
     fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
@@ -784,6 +769,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             }
         };
 
+        let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
         SyntaxExtension::new(
             sess,
             kind,
@@ -791,7 +777,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             helper_attrs,
             self.root.edition,
             Symbol::intern(name),
-            &self.get_item_attrs(id, sess),
+            &attrs,
         )
     }
 
@@ -946,14 +932,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        self.root.tables.ty.get(self, id).unwrap().decode((self, tcx))
+        self.root
+            .tables
+            .ty
+            .get(self, id)
+            .unwrap_or_else(|| panic!("Not a type: {:?}", id))
+            .decode((self, tcx))
     }
 
     fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
-        match self.is_proc_macro(id) {
-            true => self.root.proc_macro_data.as_ref().unwrap().stability,
-            false => self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)),
-        }
+        self.root.tables.stability.get(self, id).map(|stab| stab.decode(self))
     }
 
     fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> {
@@ -961,19 +949,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
-        self.root
-            .tables
-            .deprecation
-            .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
-            .map(|depr| depr.decode(self))
+        self.root.tables.deprecation.get(self, id).map(|depr| depr.decode(self))
     }
 
     fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
-        match self.is_proc_macro(id) {
-            true => ty::Visibility::Public,
-            false => self.root.tables.visibility.get(self, id).unwrap().decode(self),
-        }
+        self.root.tables.visibility.get(self, id).unwrap().decode(self)
     }
 
     fn get_impl_data(&self, id: DefIndex) -> ImplData {
@@ -1157,7 +1137,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                                 // 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);
+                                let attrs: Vec<_> =
+                                    self.get_item_attrs(def_id.index, sess).collect();
                                 if sess.contains_name(&attrs, sym::non_exhaustive) {
                                     let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
                                     vis = ty::Visibility::Restricted(crate_def_id);
@@ -1184,7 +1165,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn is_item_mir_available(&self, id: DefIndex) -> bool {
-        !self.is_proc_macro(id) && self.root.tables.mir.get(self, id).is_some()
+        self.root.tables.mir.get(self, id).is_some()
     }
 
     fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
@@ -1200,7 +1181,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .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))
             })
@@ -1216,7 +1196,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .mir_abstract_consts
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
     }
 
@@ -1225,7 +1204,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .unused_generic_params
             .get(self, id)
-            .filter(|_| !self.is_proc_macro(id))
             .map(|params| params.decode(self))
             .unwrap_or_default()
     }
@@ -1235,7 +1213,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .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))
             })
@@ -1283,8 +1260,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
-        self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self).collect()
+    fn get_item_variances(&'a self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a {
+        self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self)
     }
 
     fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
@@ -1308,7 +1285,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Vec<ast::Attribute> {
+    fn get_item_attrs(
+        &'a self,
+        node_id: DefIndex,
+        sess: &'a Session,
+    ) -> impl Iterator<Item = ast::Attribute> + 'a {
         // 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
@@ -1325,7 +1306,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .get(self, item_id)
             .unwrap_or_else(Lazy::empty)
             .decode((self, sess))
-            .collect::<Vec<_>>()
     }
 
     fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<Symbol>> {
@@ -1536,14 +1516,63 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     #[inline]
     fn def_key(&self, index: DefIndex) -> DefKey {
-        *self.def_key_cache.lock().entry(index).or_insert_with(|| {
-            let mut key = self.root.tables.def_keys.get(self, index).unwrap().decode(self);
-            if self.is_proc_macro(index) {
-                let name = self.raw_proc_macro(index).name();
-                key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
+        *self
+            .def_key_cache
+            .lock()
+            .entry(index)
+            .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
+    }
+
+    /// Finds the corresponding `DefId` for the provided `DefPathHash`, if it exists.
+    /// This is used by incremental compilation to map a serialized `DefPathHash` to
+    /// its `DefId` in the current session.
+    /// Normally, only one 'main' crate will change between incremental compilation sessions:
+    /// all dependencies will be completely unchanged. In this case, we can avoid
+    /// decoding every `DefPathHash` in the crate, since the `DefIndex` from the previous
+    /// session will still be valid. If our 'guess' is wrong (the `DefIndex` no longer exists,
+    /// or has a different `DefPathHash`, then we need to decode all `DefPathHashes` to determine
+    /// the correct mapping).
+    fn def_path_hash_to_def_id(
+        &self,
+        krate: CrateNum,
+        index_guess: u32,
+        hash: DefPathHash,
+    ) -> Option<DefId> {
+        let def_index_guess = DefIndex::from_u32(index_guess);
+        let old_hash = self
+            .root
+            .tables
+            .def_path_hashes
+            .get(self, def_index_guess)
+            .map(|lazy| lazy.decode(self));
+
+        // Fast path: the definition and its index is unchanged from the
+        // previous compilation session. There is no need to decode anything
+        // else
+        if old_hash == Some(hash) {
+            return Some(DefId { krate, index: def_index_guess });
+        }
+
+        let is_proc_macro = self.is_proc_macro_crate();
+
+        // Slow path: We need to find out the new `DefIndex` of the provided
+        // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
+        // stored in this crate.
+        let map = self.cdata.def_path_hash_map.get_or_init(|| {
+            let end_id = self.root.tables.def_path_hashes.size() as u32;
+            let mut map = FxHashMap::with_capacity_and_hasher(end_id as usize, Default::default());
+            for i in 0..end_id {
+                let def_index = DefIndex::from_u32(i);
+                // There may be gaps in the encoded table if we're decoding a proc-macro crate
+                if let Some(hash) = self.root.tables.def_path_hashes.get(self, def_index) {
+                    map.insert(hash.decode(self), def_index);
+                } else if !is_proc_macro {
+                    panic!("Missing def_path_hashes entry for {:?}", def_index);
+                }
             }
-            key
-        })
+            map
+        });
+        map.get(&hash).map(|index| DefId { krate, index: *index })
     }
 
     // Returns the path leading to the thing with this `id`.
@@ -1568,23 +1597,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
-    fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
-        let mut def_path_hashes = self.def_path_hash_cache.lock();
-        let mut def_index_to_data = |index| {
-            (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
-        };
-        if let Some(data) = &self.root.proc_macro_data {
-            std::iter::once(CRATE_DEF_INDEX)
-                .chain(data.macros.decode(self))
-                .map(def_index_to_data)
-                .collect()
-        } else {
-            (0..self.num_def_ids())
-                .map(|index| def_index_to_data(DefIndex::from_usize(index)))
-                .collect()
-        }
-    }
-
     /// Get the `DepNodeIndex` corresponding this crate. The result of this
     /// method is cached in the `dep_node_index` field.
     fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
@@ -1824,6 +1836,7 @@ impl CrateMetadata {
             trait_impls,
             raw_proc_macros,
             source_map_import_info: OnceCell::new(),
+            def_path_hash_map: Default::default(),
             alloc_decoding_state,
             dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
             cnum,