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.
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,
}
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 {}",
}
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 {
}
};
+ let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
SyntaxExtension::new(
sess,
kind,
helper_attrs,
self.root.edition,
Symbol::intern(name),
- &self.get_item_attrs(id, sess),
+ &attrs,
)
}
}
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> {
}
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 {
// 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);
}
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 {
.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))
})
.tables
.mir_abstract_consts
.get(self, id)
- .filter(|_| !self.is_proc_macro(id))
.map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
}
.tables
.unused_generic_params
.get(self, id)
- .filter(|_| !self.is_proc_macro(id))
.map(|params| params.decode(self))
.unwrap_or_default()
}
.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))
})
}
}
- 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 {
}
}
- 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
.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>> {
#[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`.
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 {
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,