Repository navigation
Remap def indices for deterministic metadata encoding #162809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,7 +21,7 @@ use rustc_hir as hir; | |
| use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; | ||
| use rustc_hir::definitions::DefPathData; | ||
| use rustc_hir_pretty::id_to_string; | ||
| use rustc_index::IndexVec; | ||
| use rustc_index::{Idx, IndexVec}; | ||
| use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; | ||
| use rustc_middle::hir::map::compute_hir_hash; | ||
| use rustc_middle::middle::dependency_format::Linkage; | ||
|
|
@@ -78,6 +78,8 @@ pub(super) struct EncodeContext<'a, 'tcx> { | |
| hygiene_ctxt: Rc<RefCell<HygieneEncodeContext>>, | ||
| // Used for both `Symbol`s and `ByteSymbol`s. | ||
| symbol_index_table: FxHashMap<u32, usize>, | ||
| pub(super) def_indexes_remapping: FxHashMap<DefIndex, DefIndex>, | ||
| last_deterministic_index: u32, | ||
| } | ||
|
|
||
| /// If the current crate is a proc-macro, returns early with `LazyArray::default()`. | ||
|
|
@@ -156,12 +158,14 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { | |
| } | ||
|
|
||
| fn encode_def_index(&mut self, def_index: DefIndex) { | ||
| self.emit_u32(def_index.as_u32()); | ||
| self.emit_u32(self.map_index(def_index).as_u32()); | ||
| } | ||
|
|
||
| fn encode_def_id(&mut self, def_id: DefId) { | ||
| let def_id = self.map_def_id(def_id); | ||
|
|
||
| def_id.krate.encode(self); | ||
| def_id.index.encode(self); | ||
| self.emit_u32(def_id.index.as_u32()); | ||
| } | ||
|
|
||
| fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) { | ||
|
|
@@ -409,20 +413,23 @@ macro_rules! record_some_lazy { | |
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ | ||
| let value = $value; | ||
| let lazy = $self.lazy(value); | ||
| $self.$tables.$table.set_some($def_id.index, lazy); | ||
| let def_id = $self.map_def_id($def_id); | ||
| $self.$tables.$table.set_some(def_id.index, lazy); | ||
| }}; | ||
| } | ||
|
|
||
| macro_rules! record_some { | ||
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { | ||
| $self.$tables.$table.set_some($def_id.index, $value) | ||
| }; | ||
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ | ||
| let def_id = $self.map_def_id($def_id); | ||
| $self.$tables.$table.set_some(def_id.index, $value) | ||
| }}; | ||
| } | ||
|
|
||
| macro_rules! record_value { | ||
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { | ||
| $self.$tables.$table.set($def_id.index, $value) | ||
| }; | ||
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ | ||
| let def_id = $self.map_def_id($def_id); | ||
| $self.$tables.$table.set(def_id.index, $value) | ||
| }}; | ||
| } | ||
|
|
||
| // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would | ||
|
|
@@ -431,15 +438,17 @@ macro_rules! record_array { | |
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ | ||
| let value = $value; | ||
| let lazy = $self.lazy_array(value); | ||
| $self.$tables.$table.set_some($def_id.index, lazy); | ||
| let def_id = $self.map_def_id($def_id); | ||
| $self.$tables.$table.set_some(def_id.index, lazy); | ||
| }}; | ||
| } | ||
|
|
||
| macro_rules! record_defaulted_array { | ||
| ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ | ||
| let value = $value; | ||
| let lazy = $self.lazy_array(value); | ||
| $self.$tables.$table.set($def_id.index, lazy); | ||
| let def_id = $self.map_def_id($def_id); | ||
| $self.$tables.$table.set(def_id.index, lazy); | ||
| }}; | ||
| } | ||
|
|
||
|
|
@@ -528,7 +537,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| } | ||
| } | ||
|
|
||
| fn encode_def_path_table(&mut self) { | ||
| fn encode_def_path_table(&mut self, sorted_ids: &[LocalDefId]) { | ||
| let defs = self.tcx.definitions(); | ||
| if self.is_proc_macro { | ||
| for def_id in std::iter::once(CRATE_DEF_ID) | ||
|
|
@@ -542,10 +551,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| record_value!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) | ||
| } | ||
| } else { | ||
| for (def_index, def_key, def_path_hash) in defs.enumerated_keys_and_path_hashes() { | ||
| let def_id = LocalDefId { local_def_index: def_index }.to_def_id(); | ||
| for &def_id in sorted_ids { | ||
| let def_key = defs.def_key(def_id); | ||
| let hash = defs.def_path_hash(def_id).local_hash().as_u64(); | ||
|
|
||
| let def_id = def_id.to_def_id(); | ||
|
|
||
| record_some_lazy!(self.tables.def_keys[def_id] <- def_key); | ||
| record_value!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) | ||
| record_value!(self.tables.def_path_hashes[def_id] <- hash); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -624,7 +637,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| adapted.encode(&mut self.opaque) | ||
| } | ||
|
|
||
| fn encode_crate_root(&mut self) -> (LazyValue<CrateRoot>, LazyValue<CrateRootUnhashed>) { | ||
| fn encode_crate_root( | ||
| &mut self, | ||
| remapping: FxHashMap<DefIndex, DefIndex>, | ||
| sorted_ids: Vec<LocalDefId>, | ||
| ) -> (LazyValue<CrateRoot>, LazyValue<CrateRootUnhashed>) { | ||
| self.def_indexes_remapping = remapping; | ||
|
|
||
| let tcx = self.tcx; | ||
| let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32); | ||
|
|
||
|
|
@@ -667,7 +686,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
|
|
||
| let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules()); | ||
|
|
||
| _ = stat!("def-path-table", || self.encode_def_path_table()); | ||
| _ = stat!("def-path-table", || self.encode_def_path_table(&sorted_ids)); | ||
|
|
||
| // Encode the def IDs of traits, for rustdoc and diagnostics. | ||
| let traits = stat!("traits", || self.encode_traits()); | ||
|
|
@@ -679,7 +698,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
|
|
||
| _ = stat!("mir", || self.encode_mir()); | ||
|
|
||
| _ = stat!("def-ids", || self.encode_def_ids()); | ||
| _ = stat!("def-ids", || self.encode_def_ids(&sorted_ids)); | ||
|
|
||
| let interpret_alloc_index = stat!("interpret-alloc-index", || { | ||
| let mut interpret_alloc_index = Vec::new(); | ||
|
|
@@ -1455,7 +1474,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| record_value!(self.tables.attr_flags[def_id.to_def_id()] <- attr_flags) | ||
| } | ||
|
|
||
| fn encode_def_ids(&mut self) { | ||
| fn map_def_id(&self, def_id: DefId) -> DefId { | ||
| if def_id.is_local() { | ||
| DefId { krate: LOCAL_CRATE, index: self.map_index(def_id.index) } | ||
| } else { | ||
| def_id | ||
| } | ||
| } | ||
|
|
||
| #[inline] | ||
| fn map_index(&self, def_index: DefIndex) -> DefIndex { | ||
| let index = def_index.as_u32(); | ||
|
|
||
| if index <= self.last_deterministic_index { | ||
| def_index | ||
| } else { | ||
| self.def_indexes_remapping.get(&def_index).copied().unwrap_or(def_index) | ||
| } | ||
| } | ||
|
|
||
| fn encode_def_ids(&mut self, sorted_ids: &[LocalDefId]) { | ||
| self.encode_info_for_mod(CRATE_DEF_ID); | ||
|
|
||
| // Proc-macro crates only export proc-macro items, which are looked | ||
|
|
@@ -1465,8 +1503,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| } | ||
|
|
||
| let tcx = self.tcx; | ||
|
|
||
| for local_id in tcx.iter_local_def_id() { | ||
| for &local_id in sorted_ids { | ||
| let def_id = local_id.to_def_id(); | ||
| let def_kind = tcx.def_kind(local_id); | ||
| record_some!(self.tables.def_kind[def_id] <- def_kind); | ||
|
|
@@ -2302,7 +2339,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
| if let Ok(mut an) = trait_def.ancestors(tcx, def_id) | ||
| && let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) | ||
| { | ||
| record_some!(self.tables.impl_parent[def_id] <- parent.into()); | ||
| record_some!(self.tables.impl_parent[def_id] <- self.map_def_id(parent).into()); | ||
| } | ||
|
|
||
| // if this is an impl of `CoerceUnsized`, create its | ||
|
|
@@ -2316,9 +2353,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
|
|
||
| let trait_impls: Vec<_> = trait_impls | ||
| .into_iter() | ||
| .map(|(trait_def_id, impls)| TraitImpls { | ||
| trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), | ||
| impls: self.lazy_array(&impls), | ||
| .map(|(trait_id, impls)| { | ||
| let trait_id = self.map_def_id(trait_id); | ||
| TraitImpls { | ||
| trait_id: (trait_id.krate.as_u32(), trait_id.index.as_u32()), | ||
| impls: self.lazy_array(&impls), | ||
| } | ||
| }) | ||
| .collect(); | ||
|
|
||
|
|
@@ -2601,7 +2641,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { | |
| with_encode_metadata_header(tcx, path, |ecx| { | ||
| // Encode all the entries and extra information in the crate, | ||
| // culminating in the `CrateRoot` which points to all of it. | ||
| let (root, unhashed) = ecx.encode_crate_root(); | ||
| let (remapping, sequence) = create_def_index_remapping(tcx); | ||
|
|
||
| let (root, unhashed) = ecx.encode_crate_root(remapping, sequence); | ||
|
|
||
| // Flush buffer to ensure backing file has the correct size. | ||
| ecx.opaque.flush(); | ||
|
|
@@ -2634,6 +2676,40 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { | |
| } | ||
| } | ||
|
|
||
| fn create_def_index_remapping(tcx: TyCtxt<'_>) -> (FxHashMap<DefIndex, DefIndex>, Vec<LocalDefId>) { | ||
| let defs = tcx.untracked().definitions.read(); | ||
|
|
||
| let mut to_remap = vec![]; | ||
| let mut def_ids = vec![]; | ||
|
|
||
| let start = tcx.definitions().last_deterministic_index().as_usize() + 1; | ||
| for idx in start..defs.num_definitions() { | ||
| let def_id = LocalDefId { local_def_index: idx.into() }; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this could iterate backwards, stopping when it hits an index not needing remapping. Remapped indices should be at the end |
||
|
|
||
| to_remap.push((def_id, defs.def_path_hash(def_id).local_hash())); | ||
| def_ids.push(def_id); | ||
| } | ||
|
|
||
| to_remap.sort_by_key(|(_, hash)| *hash); | ||
|
|
||
| let mut remapping = FxHashMap::default(); | ||
| for ((orig_id, _), remapped_id) in to_remap.into_iter().zip(def_ids) { | ||
| remapping.insert(orig_id.local_def_index, remapped_id.local_def_index); | ||
| } | ||
|
|
||
| let mut sorted_def_ids = (0..defs.num_definitions()) | ||
| .into_iter() | ||
| .map(|idx| LocalDefId { local_def_index: DefIndex::new(idx) }) | ||
| .collect::<Vec<_>>(); | ||
|
|
||
| sorted_def_ids.sort_by_key(|id| { | ||
| let def_index = id.local_def_index; | ||
| remapping.get(&def_index).copied().unwrap_or(def_index) | ||
| }); | ||
|
|
||
| (remapping, sorted_def_ids) | ||
| } | ||
|
|
||
| fn with_encode_metadata_header( | ||
| tcx: TyCtxt<'_>, | ||
| path: &Path, | ||
|
|
@@ -2707,6 +2783,8 @@ fn with_encode_metadata_header( | |
| is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro), | ||
| hygiene_ctxt: Default::default(), | ||
| symbol_index_table: Default::default(), | ||
| def_indexes_remapping: Default::default(), | ||
| last_deterministic_index: tcx.definitions().last_deterministic_index().as_u32(), | ||
| }; | ||
|
|
||
| // Encode the rustc version string in a predictable location. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -378,7 +378,7 @@ pub(crate) struct CrateDep { | |
|
|
||
| #[derive(MetadataEncodable, LazyDecodable)] | ||
| pub(crate) struct TraitImpls { | ||
| trait_id: (u32, DefIndex), | ||
| trait_id: (u32 /* crate */, u32 /* def index */), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why was this changed? |
||
| impls: LazyArray<(DefIndex, Option<SimplifiedType>)>, | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| async fn test1(_: &'_ u8) {} | ||
| async fn test2<'s>(_: &'s u8) {} | ||
| fn main() {} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will this ever be empty? shouldn't the first entry always be the crate root?
View changes since the review