diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index df4bb2502cbeb..2a31a051d2769 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -75,10 +75,6 @@ crate struct CrateMetadata { /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. def_path_table: DefPathTable, - /// Trait impl data. - /// FIXME: Used only from queries and can use query cache, - /// so pre-decoding can probably be avoided. - trait_impls: FxHashMap<(u32, DefIndex), Lazy<[DefIndex]>>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -1304,17 +1300,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { None => None, }; - if let Some(filter) = filter { - if let Some(impls) = self.trait_impls.get(&filter) { + if let Some((cnum, index)) = filter { + if let Some(impls) = + self.root.tables.trait_impls.get(self, cnum).and_then(|t| t.get(self, index)) + { 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))), + self.root.all_trait_impls.decode(self).map(|idx| self.local_def_id(idx)), ) } } @@ -1646,11 +1642,6 @@ impl CrateMetadata { let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || { root.def_path_table.decode((&blob, sess)) }); - let trait_impls = root - .impls - .decode((&blob, sess)) - .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) - .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); let dependencies = Lock::new(cnum_map.iter().cloned().collect()); @@ -1658,7 +1649,6 @@ impl CrateMetadata { blob, root, def_path_table, - trait_impls, raw_proc_macros, source_map_import_info: OnceCell::new(), alloc_decoding_state, diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index dc8d14a44f806..0f67a036da643 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -564,7 +564,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the def IDs of impls, for coherence checking. i = self.position(); - let impls = self.encode_impls(); + let all_trait_impls = self.encode_trait_impls(); let impl_bytes = self.position() - i; let tcx = self.tcx; @@ -677,12 +677,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { foreign_modules, source_map, def_path_table, - impls, exported_symbols, interpret_alloc_index, tables, syntax_contexts, expn_data, + all_trait_impls, }); let total_bytes = self.position(); @@ -1586,34 +1586,37 @@ impl EncodeContext<'a, 'tcx> { self.lazy(&tcx.lang_items().missing) } - /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { + fn encode_trait_impls(&mut self) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; tcx.hir().krate().visit_all_item_likes(&mut visitor); - let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); + let all_impls: Vec<_> = visitor.impls.into_iter().collect(); + let mut all_trait_impls = Vec::new(); - // Bring everything into deterministic order for hashing - all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id)); + let mut table_map: FxHashMap>> = + Default::default(); - let all_impls: Vec<_> = all_impls - .into_iter() - .map(|(trait_def_id, mut impls)| { - // Bring everything into deterministic order for hashing - impls.sort_by_cached_key(|&index| { - tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) - }); + for (trait_def_id, mut impls) in all_impls { + // Bring everything into deterministic order for hashing + impls.sort_by_cached_key(|&index| { + tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) + }); - TraitImpls { - trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy(&impls), - } - }) - .collect(); + all_trait_impls.extend(&impls); - self.lazy(&all_impls) + table_map + .entry(trait_def_id.krate.as_u32()) + .or_default() + .set(trait_def_id.index, self.lazy(&impls)); + } + + for (cnum, builder) in table_map { + let table = builder.encode(&mut self.opaque); + self.tables.trait_impls.set(cnum, table); + } + self.lazy(&all_trait_impls) } // Encodes all symbols exported from this crate into the metadata. diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 55ef66f1939c4..65ee04c793761 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -197,7 +197,7 @@ crate struct CrateRoot<'tcx> { native_libraries: Lazy<[NativeLib]>, foreign_modules: Lazy<[ForeignModule]>, def_path_table: Lazy, - impls: Lazy<[TraitImpls]>, + all_trait_impls: Lazy<[DefIndex]>, interpret_alloc_index: Lazy<[u32]>, tables: LazyTables<'tcx>, @@ -230,23 +230,17 @@ crate struct CrateDep { pub extra_filename: String, } -#[derive(RustcEncodable, RustcDecodable)] -crate struct TraitImpls { - trait_id: (u32, DefIndex), - impls: Lazy<[DefIndex]>, -} - /// Define `LazyTables` and `TableBuilders` at the same time. macro_rules! define_tables { - ($($name:ident: Table),+ $(,)?) => { + ($($name:ident: Table<$I:ty, $T:ty>),+ $(,)?) => { #[derive(RustcEncodable, RustcDecodable)] crate struct LazyTables<'tcx> { - $($name: Lazy!(Table)),+ + $($name: Lazy!(Table<$I, $T>)),+ } #[derive(Default)] struct TableBuilders<'tcx> { - $($name: TableBuilder),+ + $($name: TableBuilder<$I, $T>),+ } impl TableBuilders<'tcx> { @@ -286,6 +280,7 @@ define_tables! { mir: Table)>, promoted_mir: Table>)>, unused_generic_params: Table>>, + trait_impls: Table)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/rmeta/table.rs b/src/librustc_metadata/rmeta/table.rs index e1d0a0dbf2ffa..927b757803324 100644 --- a/src/librustc_metadata/rmeta/table.rs +++ b/src/librustc_metadata/rmeta/table.rs @@ -93,24 +93,34 @@ impl FixedSizeEncoding for Option> { } } -impl FixedSizeEncoding for Option> { - fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); +macro_rules! meta_body { + ($T:ident) => { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position_and_meta( + >>::from_bytes(b)?.position, + u32::from_bytes(&b[u32::BYTE_LEN..]) as usize, + )) + } - fn from_bytes(b: &[u8]) -> Self { - Some(Lazy::from_position_and_meta( - >>::from_bytes(b)?.position, - u32::from_bytes(&b[u32::BYTE_LEN..]) as usize, - )) - } + fn write_to_bytes(self, b: &mut [u8]) { + self.map(|lazy| Lazy::<$T>::from_position(lazy.position)).write_to_bytes(b); - fn write_to_bytes(self, b: &mut [u8]) { - self.map(|lazy| Lazy::::from_position(lazy.position)).write_to_bytes(b); + let len = self.map_or(0, |lazy| lazy.meta); + let len: u32 = len.try_into().unwrap(); + + len.write_to_bytes(&mut b[u32::BYTE_LEN..]); + } + }; +} - let len = self.map_or(0, |lazy| lazy.meta); - let len: u32 = len.try_into().unwrap(); +impl FixedSizeEncoding for Option>, usize>> { + meta_body!(T); +} - len.write_to_bytes(&mut b[u32::BYTE_LEN..]); - } +impl FixedSizeEncoding for Option> { + meta_body!(T); } /// Random-access table (i.e. offering constant-time `get`/`set`), similar to