Auto merge of #97291 - compiler-errors:lazy-is-actually-3-types-in-a-trenchcoat, r=cjgillot

Split out the various responsibilities of `rustc_metadata::Lazy`

`Lazy<T>` actually acts like three different types -- a pointer in the crate metadata to a single value, a pointer to a list/array of values, and an indexable pointer of a list of values (a table).

We currently overload `Lazy<T>` to work differently than `Lazy<[T]>` and the same for `Lazy<Table<I, T>>`. All is well with some helper adapter traits such as [`LazyQueryDecodable`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/decoder/trait.LazyQueryDecodable.html) and [`EncodeContentsForLazy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/encoder/trait.EncodeContentsForLazy.html).

Well, changes in #97287 that make `Lazy` work with the now invariant lifetime `'tcx` make these adapters fall apart because of coherence reasons. So we split out these three types and rework some of the helper traits so it's both 1. more clear to understand, and 2. compatible with the changes later in that PR.

Split out from #97287 so it can be reviewed separately, since this PR stands on its own.
This commit is contained in:
bors 2022-05-24 13:42:33 +00:00
commit ee9726cb10
6 changed files with 404 additions and 432 deletions

View File

@ -10,6 +10,7 @@
#![feature(macro_metavar_expr)] #![feature(macro_metavar_expr)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(slice_as_chunks)] #![feature(slice_as_chunks)]
#![feature(trusted_len)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(never_type)] #![feature(never_type)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -1,12 +1,10 @@
// Decoding metadata from a single crate's metadata // Decoding metadata from a single crate's metadata
use crate::creader::{CStore, CrateMetadataRef}; use crate::creader::{CStore, CrateMetadataRef};
use crate::rmeta::table::{FixedSizeEncoding, Table};
use crate::rmeta::*; use crate::rmeta::*;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_attr as attr;
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
@ -20,10 +18,8 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_hir::lang_items; use rustc_hir::lang_items;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::metadata::ModChild; use rustc_middle::metadata::ModChild;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::thir; use rustc_middle::thir;
use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::codec::TyDecoder;
@ -42,6 +38,7 @@ use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
use proc_macro::bridge::client::ProcMacro; use proc_macro::bridge::client::ProcMacro;
use std::io; use std::io;
use std::iter::TrustedLen;
use std::mem; use std::mem;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::path::Path; use std::path::Path;
@ -85,7 +82,6 @@ pub(crate) struct CrateMetadata {
blob: MetadataBlob, blob: MetadataBlob,
// --- Some data pre-decoded from the metadata blob, usually for performance --- // --- Some data pre-decoded from the metadata blob, usually for performance ---
/// Properties of the whole crate.
/// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
/// lifetime is only used behind `Lazy`, and therefore acts like a /// lifetime is only used behind `Lazy`, and therefore acts like a
/// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
@ -94,12 +90,12 @@ pub(crate) struct CrateMetadata {
/// Trait impl data. /// Trait impl data.
/// FIXME: Used only from queries and can use query cache, /// FIXME: Used only from queries and can use query cache,
/// so pre-decoding can probably be avoided. /// so pre-decoding can probably be avoided.
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<SimplifiedType>)]>>, trait_impls: FxHashMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
/// Inherent impls which do not follow the normal coherence rules. /// Inherent impls which do not follow the normal coherence rules.
/// ///
/// These can be introduced using either `#![rustc_coherence_is_core]` /// These can be introduced using either `#![rustc_coherence_is_core]`
/// or `#[rustc_allow_incoherent_impl]`. /// or `#[rustc_allow_incoherent_impl]`.
incoherent_impls: FxHashMap<SimplifiedType, Lazy<[DefIndex]>>, incoherent_impls: FxHashMap<SimplifiedType, LazyArray<DefIndex>>,
/// Proc macro descriptions for this crate, if it's a proc macro crate. /// Proc macro descriptions for this crate, if it's a proc macro crate.
raw_proc_macros: Option<&'static [ProcMacro]>, raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate. /// Source maps for code from the crate.
@ -265,7 +261,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) {
} }
} }
impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> { impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> LazyValue<T> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T { fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get()); let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position); dcx.lazy_state = LazyState::NodeStart(self.position);
@ -273,130 +269,41 @@ impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> {
} }
} }
impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> { struct DecodeIterator<'a, 'tcx, T> {
fn decode<M: Metadata<'a, 'tcx>>( elem_counter: std::ops::Range<usize>,
self, dcx: DecodeContext<'a, 'tcx>,
metadata: M, _phantom: PhantomData<fn() -> T>,
) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x { }
impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Iterator for DecodeIterator<'a, 'tcx, T> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.elem_counter.next().map(|_| T::decode(&mut self.dcx))
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.elem_counter.size_hint()
}
}
impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> ExactSizeIterator
for DecodeIterator<'a, 'tcx, T>
{
}
unsafe impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> TrustedLen
for DecodeIterator<'a, 'tcx, T>
{
}
impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> LazyArray<T> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> DecodeIterator<'a, 'tcx, T> {
let mut dcx = metadata.decoder(self.position.get()); let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position); dcx.lazy_state = LazyState::NodeStart(self.position);
(0..self.meta).map(move |_| T::decode(&mut dcx)) DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData }
}
}
trait LazyQueryDecodable<'a, 'tcx, T> {
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
err: impl FnOnce() -> !,
) -> T;
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for T {
fn decode_query(self, _: CrateMetadataRef<'a>, _: TyCtxt<'tcx>, _: impl FnOnce() -> !) -> T {
self
}
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for Option<T> {
fn decode_query(self, _: CrateMetadataRef<'a>, _: TyCtxt<'tcx>, err: impl FnOnce() -> !) -> T {
if let Some(l) = self { l } else { err() }
}
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for Option<Lazy<T>>
where
T: Decodable<DecodeContext<'a, 'tcx>>,
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
err: impl FnOnce() -> !,
) -> T {
if let Some(l) = self { l.decode((cdata, tcx)) } else { err() }
}
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, &'tcx T> for Option<Lazy<T>>
where
T: Decodable<DecodeContext<'a, 'tcx>>,
T: ArenaAllocatable<'tcx>,
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
err: impl FnOnce() -> !,
) -> &'tcx T {
if let Some(l) = self { tcx.arena.alloc(l.decode((cdata, tcx))) } else { err() }
}
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, Option<T>> for Option<Lazy<T>>
where
T: Decodable<DecodeContext<'a, 'tcx>>,
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
_err: impl FnOnce() -> !,
) -> Option<T> {
self.map(|l| l.decode((cdata, tcx)))
}
}
impl<'a, 'tcx, T, E> LazyQueryDecodable<'a, 'tcx, Result<Option<T>, E>> for Option<Lazy<T>>
where
T: Decodable<DecodeContext<'a, 'tcx>>,
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
_err: impl FnOnce() -> !,
) -> Result<Option<T>, E> {
Ok(self.map(|l| l.decode((cdata, tcx))))
}
}
impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, &'tcx [T]> for Option<Lazy<[T], usize>>
where
T: Decodable<DecodeContext<'a, 'tcx>> + Copy,
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
_err: impl FnOnce() -> !,
) -> &'tcx [T] {
if let Some(l) = self { tcx.arena.alloc_from_iter(l.decode((cdata, tcx))) } else { &[] }
}
}
impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option<DeprecationEntry>>
for Option<Lazy<attr::Deprecation>>
{
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
tcx: TyCtxt<'tcx>,
_err: impl FnOnce() -> !,
) -> Option<DeprecationEntry> {
self.map(|l| l.decode((cdata, tcx))).map(DeprecationEntry::external)
}
}
impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option<DefId>> for Option<RawDefId> {
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
_: TyCtxt<'tcx>,
_: impl FnOnce() -> !,
) -> Option<DefId> {
self.map(|raw_def_id| raw_def_id.decode(cdata))
} }
} }
@ -423,7 +330,8 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
self.cdata().map_encoded_cnum_to_current(cnum) self.cdata().map_encoded_cnum_to_current(cnum)
} }
fn read_lazy_with_meta<T: ?Sized + LazyMeta>(&mut self, meta: T::Meta) -> Lazy<T> { #[inline]
fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZeroUsize) -> T) -> T {
let distance = self.read_usize(); let distance = self.read_usize();
let position = match self.lazy_state { let position = match self.lazy_state {
LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
@ -434,8 +342,21 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
} }
LazyState::Previous(last_pos) => last_pos.get() + distance, LazyState::Previous(last_pos) => last_pos.get() + distance,
}; };
self.lazy_state = LazyState::Previous(NonZeroUsize::new(position).unwrap()); let position = NonZeroUsize::new(position).unwrap();
Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta) self.lazy_state = LazyState::Previous(position);
f(position)
}
fn read_lazy<T>(&mut self) -> LazyValue<T> {
self.read_lazy_offset_then(|pos| LazyValue::from_position(pos))
}
fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> {
self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
}
fn read_lazy_table<I, T>(&mut self, len: usize) -> LazyTable<I, T> {
self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, len))
} }
#[inline] #[inline]
@ -714,36 +635,29 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx
} }
} }
impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>> impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
for Lazy<T>
{
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
decoder.read_lazy_with_meta(()) decoder.read_lazy()
} }
} }
impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>> impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
for Lazy<[T]>
{
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
let len = decoder.read_usize(); let len = decoder.read_usize();
if len == 0 { Lazy::empty() } else { decoder.read_lazy_with_meta(len) } if len == 0 { LazyArray::empty() } else { decoder.read_lazy_array(len) }
} }
} }
impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for Lazy<Table<I, T>> impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> {
where
Option<T>: FixedSizeEncoding,
{
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
let len = decoder.read_usize(); let len = decoder.read_usize();
decoder.read_lazy_with_meta(len) decoder.read_lazy_table(len)
} }
} }
implement_ty_decoder!(DecodeContext<'a, 'tcx>); implement_ty_decoder!(DecodeContext<'a, 'tcx>);
impl<'tcx> MetadataBlob { impl MetadataBlob {
pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob { pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
MetadataBlob(Lrc::new(metadata_ref)) MetadataBlob(Lrc::new(metadata_ref))
} }
@ -753,18 +667,18 @@ impl<'tcx> MetadataBlob {
} }
pub(crate) fn get_rustc_version(&self) -> String { pub(crate) fn get_rustc_version(&self) -> String {
Lazy::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap()) LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap())
.decode(self) .decode(self)
} }
pub(crate) fn get_root(&self) -> CrateRoot<'tcx> { pub(crate) fn get_root<'tcx>(&self) -> CrateRoot<'tcx> {
let slice = &self.blob()[..]; let slice = &self.blob()[..];
let offset = METADATA_HEADER.len(); let offset = METADATA_HEADER.len();
let pos = (((slice[offset + 0] as u32) << 24) let pos = (((slice[offset + 0] as u32) << 24)
| ((slice[offset + 1] as u32) << 16) | ((slice[offset + 1] as u32) << 16)
| ((slice[offset + 2] as u32) << 8) | ((slice[offset + 2] as u32) << 8)
| ((slice[offset + 3] as u32) << 0)) as usize; | ((slice[offset + 3] as u32) << 0)) as usize;
Lazy::<CrateRoot<'tcx>>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) LazyValue::<CrateRoot<'tcx>>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
} }
pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> {
@ -963,7 +877,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.children .children
.get(self, index) .get(self, index)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(|index| ty::FieldDef { .map(|index| ty::FieldDef {
did: self.local_def_id(index), did: self.local_def_id(index),
@ -996,7 +910,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.children .children
.get(self, item_id) .get(self, item_id)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(|index| self.get_variant(&self.kind(index), index, did)) .map(|index| self.get_variant(&self.kind(index), index, did))
.collect() .collect()
@ -1016,7 +930,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
} }
fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> { fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self)) self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
} }
fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
@ -1202,7 +1116,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.children .children
.get(self, id) .get(self, id)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode((self, sess)) .decode((self, sess))
.map(move |child_index| self.local_def_id(child_index)) .map(move |child_index| self.local_def_id(child_index))
} }
@ -1278,7 +1192,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.children .children
.get(self, id) .get(self, id)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(move |index| respan(self.get_span(index, sess), self.item_name(index))) .map(move |index| respan(self.get_span(index, sess), self.item_name(index)))
} }
@ -1288,7 +1202,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.children .children
.get(self, id) .get(self, id)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(move |field_index| self.get_visibility(field_index)) .map(move |field_index| self.get_visibility(field_index))
} }
@ -1303,7 +1217,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.inherent_impls .inherent_impls
.get(self, id) .get(self, id)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(|index| self.local_def_id(index)), .map(|index| self.local_def_id(index)),
) )
@ -1318,7 +1232,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables .tables
.inherent_impls .inherent_impls
.get(self, ty_index) .get(self, ty_index)
.unwrap_or_else(Lazy::empty) .unwrap_or_else(LazyArray::empty)
.decode(self) .decode(self)
.map(move |impl_index| (ty_def_id, self.local_def_id(impl_index))) .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
}) })

View File

@ -1,14 +1,16 @@
use super::LazyQueryDecodable;
use crate::creader::{CStore, LoadedMacro}; use crate::creader::{CStore, LoadedMacro};
use crate::foreign_modules; use crate::foreign_modules;
use crate::native_libs; use crate::native_libs;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr::Deprecation;
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::metadata::ModChild; use rustc_middle::metadata::ModChild;
use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_middle::ty::{self, TyCtxt, Visibility};
@ -23,15 +25,80 @@ use rustc_data_structures::sync::Lrc;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::any::Any; use std::any::Any;
use super::{Decodable, DecodeContext, DecodeIterator};
trait ProcessQueryValue<'tcx, T> {
fn process_decoded(self, _tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> T;
}
impl<T> ProcessQueryValue<'_, Option<T>> for Option<T> {
#[inline(always)]
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<T> {
self
}
}
impl<T> ProcessQueryValue<'_, T> for Option<T> {
#[inline(always)]
fn process_decoded(self, _tcx: TyCtxt<'_>, err: impl Fn() -> !) -> T {
if let Some(value) = self { value } else { err() }
}
}
impl<'tcx, T: ArenaAllocatable<'tcx>> ProcessQueryValue<'tcx, &'tcx T> for Option<T> {
#[inline(always)]
fn process_decoded(self, tcx: TyCtxt<'tcx>, err: impl Fn() -> !) -> &'tcx T {
if let Some(value) = self { tcx.arena.alloc(value) } else { err() }
}
}
impl<T, E> ProcessQueryValue<'_, Result<Option<T>, E>> for Option<T> {
#[inline(always)]
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Result<Option<T>, E> {
Ok(self)
}
}
impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>> ProcessQueryValue<'tcx, &'tcx [T]>
for Option<DecodeIterator<'a, 'tcx, T>>
{
#[inline(always)]
fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> &'tcx [T] {
if let Some(iter) = self { tcx.arena.alloc_from_iter(iter) } else { &[] }
}
}
impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
#[inline(always)]
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
self.map(DeprecationEntry::external)
}
}
macro_rules! provide_one { macro_rules! provide_one {
(<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table }) => { (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table }) => {
provide_one! { provide_one! {
<$lt> $tcx, $def_id, $other, $cdata, $name => { <$lt> $tcx, $def_id, $other, $cdata, $name => {
$cdata.root.tables.$name.get($cdata, $def_id.index).decode_query( $cdata
$cdata, .root
$tcx, .tables
|| panic!("{:?} does not have a {:?}", $def_id, stringify!($name)), .$name
) .get($cdata, $def_id.index)
.map(|lazy| lazy.decode(($cdata, $tcx)))
.process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name)))
}
}
};
(<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => {
provide_one! {
<$lt> $tcx, $def_id, $other, $cdata, $name => {
// We don't decode `table_direct`, since it's not a Lazy, but an actual value
$cdata
.root
.tables
.$name
.get($cdata, $def_id.index)
.process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name)))
} }
} }
}; };
@ -143,15 +210,15 @@ provide! { <'tcx> tcx, def_id, other, cdata,
lookup_deprecation_entry => { table } lookup_deprecation_entry => { table }
visibility => { table } visibility => { table }
unused_generic_params => { table } unused_generic_params => { table }
opt_def_kind => { table } opt_def_kind => { table_direct }
impl_parent => { table } impl_parent => { table }
impl_polarity => { table } impl_polarity => { table_direct }
impl_defaultness => { table } impl_defaultness => { table_direct }
impl_constness => { table } impl_constness => { table_direct }
coerce_unsized_info => { table } coerce_unsized_info => { table }
mir_const_qualif => { table } mir_const_qualif => { table }
rendered_const => { table } rendered_const => { table }
asyncness => { table } asyncness => { table_direct }
fn_arg_names => { table } fn_arg_names => { table }
generator_kind => { table } generator_kind => { table }
trait_def => { table } trait_def => { table }

View File

@ -1,5 +1,5 @@
use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::table::TableBuilder;
use crate::rmeta::*; use crate::rmeta::*;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
@ -17,7 +17,6 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items; use rustc_hir::lang_items;
use rustc_hir::{AnonConst, GenericParamKind}; use rustc_hir::{AnonConst, GenericParamKind};
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_index::vec::Idx;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{ use rustc_middle::middle::exported_symbols::{
@ -38,6 +37,7 @@ use rustc_span::{
self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext, self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
}; };
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use std::borrow::Borrow;
use std::hash::Hash; use std::hash::Hash;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use tracing::{debug, trace}; use tracing::{debug, trace};
@ -79,7 +79,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
macro_rules! empty_proc_macro { macro_rules! empty_proc_macro {
($self:ident) => { ($self:ident) => {
if $self.is_proc_macro { if $self.is_proc_macro {
return Lazy::empty(); return LazyArray::empty();
} }
}; };
} }
@ -124,33 +124,26 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
} }
} }
impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>> impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
for Lazy<T>
{
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
e.emit_lazy_distance(*self) e.emit_lazy_distance(self.position)
} }
} }
impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>> impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
for Lazy<[T]>
{
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
e.emit_usize(self.meta)?; e.emit_usize(self.num_elems)?;
if self.meta == 0 { if self.num_elems == 0 {
return Ok(()); return Ok(());
} }
e.emit_lazy_distance(*self) e.emit_lazy_distance(self.position)
} }
} }
impl<'a, 'tcx, I: Idx, T> Encodable<EncodeContext<'a, 'tcx>> for Lazy<Table<I, T>> impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
where
Option<T>: FixedSizeEncoding,
{
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
e.emit_usize(self.meta)?; e.emit_usize(self.encoded_size)?;
e.emit_lazy_distance(*self) e.emit_lazy_distance(self.position)
} }
} }
@ -345,34 +338,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
} }
} }
/// Helper trait to allow overloading `EncodeContext::lazy` for iterators. // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
trait EncodeContentsForLazy<'a, 'tcx, T: ?Sized + LazyMeta> {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
}
impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for &T {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
self.encode(ecx).unwrap()
}
}
impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for T {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
self.encode(ecx).unwrap()
}
}
impl<'a, 'tcx, I, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, [T]> for I
where
I: IntoIterator,
I::Item: EncodeContentsForLazy<'a, 'tcx, T>,
{
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
}
}
// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows. // normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record { macro_rules! record {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
@ -384,12 +350,24 @@ macro_rules! record {
}}; }};
} }
// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
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($def_id.index, lazy);
}
}};
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn emit_lazy_distance<T: ?Sized + LazyMeta>( fn emit_lazy_distance(
&mut self, &mut self,
lazy: Lazy<T>, position: NonZeroUsize,
) -> Result<(), <Self as Encoder>::Error> { ) -> Result<(), <Self as Encoder>::Error> {
let pos = lazy.position.get(); let pos = position.get();
let distance = match self.lazy_state { let distance = match self.lazy_state {
LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
LazyState::NodeStart(start) => { LazyState::NodeStart(start) => {
@ -399,31 +377,51 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
LazyState::Previous(last_pos) => { LazyState::Previous(last_pos) => {
assert!( assert!(
last_pos <= lazy.position, last_pos <= position,
"make sure that the calls to `lazy*` \ "make sure that the calls to `lazy*` \
are in the same order as the metadata fields", are in the same order as the metadata fields",
); );
lazy.position.get() - last_pos.get() position.get() - last_pos.get()
} }
}; };
self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap()); self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap());
self.emit_usize(distance) self.emit_usize(distance)
} }
fn lazy<T: ?Sized + LazyMeta>( fn lazy<T: Encodable<EncodeContext<'a, 'tcx>>, B: Borrow<T>>(
&mut self, &mut self,
value: impl EncodeContentsForLazy<'a, 'tcx, T>, value: B,
) -> Lazy<T> { ) -> LazyValue<T> {
let pos = NonZeroUsize::new(self.position()).unwrap(); let pos = NonZeroUsize::new(self.position()).unwrap();
assert_eq!(self.lazy_state, LazyState::NoNode); assert_eq!(self.lazy_state, LazyState::NoNode);
self.lazy_state = LazyState::NodeStart(pos); self.lazy_state = LazyState::NodeStart(pos);
let meta = value.encode_contents_for_lazy(self); value.borrow().encode(self).unwrap();
self.lazy_state = LazyState::NoNode; self.lazy_state = LazyState::NoNode;
assert!(pos.get() <= self.position()); assert!(pos.get() <= self.position());
Lazy::from_position_and_meta(pos, meta) LazyValue::from_position(pos)
}
fn lazy_array<
T: Encodable<EncodeContext<'a, 'tcx>>,
I: IntoIterator<Item = B>,
B: Borrow<T>,
>(
&mut self,
values: I,
) -> LazyArray<T> {
let pos = NonZeroUsize::new(self.position()).unwrap();
assert_eq!(self.lazy_state, LazyState::NoNode);
self.lazy_state = LazyState::NodeStart(pos);
let len = values.into_iter().map(|value| value.borrow().encode(self).unwrap()).count();
self.lazy_state = LazyState::NoNode;
assert!(pos.get() <= self.position());
LazyArray::from_position_and_num_elems(pos, len)
} }
fn encode_info_for_items(&mut self) { fn encode_info_for_items(&mut self) {
@ -458,13 +456,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
} }
fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> { fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'tcx>> {
self.lazy(DefPathHashMapRef::BorrowedFromTcx( self.lazy(DefPathHashMapRef::BorrowedFromTcx(
self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(), self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(),
)) ))
} }
fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> { fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> {
let source_map = self.tcx.sess.source_map(); let source_map = self.tcx.sess.source_map();
let all_source_files = source_map.files(); let all_source_files = source_map.files();
@ -534,10 +532,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.lazy(adapted.iter().map(|rc| &**rc)) self.lazy_array(adapted.iter().map(|rc| &**rc))
} }
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> { fn encode_crate_root(&mut self) -> LazyValue<CrateRoot<'tcx>> {
let tcx = self.tcx; let tcx = self.tcx;
let mut i = self.position(); let mut i = self.position();
@ -619,7 +617,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
n = new_n; n = new_n;
} }
self.lazy(interpret_alloc_index) self.lazy_array(interpret_alloc_index)
}; };
// Encode the proc macro data. This affects 'tables', // Encode the proc macro data. This affects 'tables',
@ -951,7 +949,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
.iter() .iter()
.filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty())); .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty()));
record!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone()); record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
if attrs.any(|attr| attr.may_have_doc_links()) { if attrs.any(|attr| attr.may_have_doc_links()) {
self.tables.may_have_doc_links.set(def_id.local_def_index, ()); self.tables.may_have_doc_links.set(def_id.local_def_index, ());
} }
@ -984,7 +982,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
if should_encode_variances(def_kind) { if should_encode_variances(def_kind) {
let v = self.tcx.variances_of(def_id); let v = self.tcx.variances_of(def_id);
record!(self.tables.variances_of[def_id] <- v); record_array!(self.tables.variances_of[def_id] <- v);
} }
if should_encode_generics(def_kind) { if should_encode_generics(def_kind) {
let g = tcx.generics_of(def_id); let g = tcx.generics_of(def_id);
@ -992,7 +990,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
let inferred_outlives = self.tcx.inferred_outlives_of(def_id); let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
if !inferred_outlives.is_empty() { if !inferred_outlives.is_empty() {
record!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
} }
} }
if let DefKind::Trait | DefKind::TraitAlias = def_kind { if let DefKind::Trait | DefKind::TraitAlias = def_kind {
@ -1004,7 +1002,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if implementations.is_empty() { if implementations.is_empty() {
continue; continue;
} }
record!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| { record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
assert!(def_id.is_local()); assert!(def_id.is_local());
def_id.index def_id.index
})); }));
@ -1031,7 +1029,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data))); record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
self.tables.impl_constness.set(def_id.index, hir::Constness::Const); self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
assert!(f.did.is_local()); assert!(f.did.is_local());
f.did.index f.did.index
})); }));
@ -1079,11 +1077,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// items - we encode information about proc-macros later on. // items - we encode information about proc-macros later on.
let reexports = if !self.is_proc_macro { let reexports = if !self.is_proc_macro {
match tcx.module_reexports(local_def_id) { match tcx.module_reexports(local_def_id) {
Some(exports) => self.lazy(exports), Some(exports) => self.lazy_array(exports),
_ => Lazy::empty(), _ => LazyArray::empty(),
} }
} else { } else {
Lazy::empty() LazyArray::empty()
}; };
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports)); record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
@ -1091,7 +1089,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// Encode this here because we don't do it in encode_def_ids. // Encode this here because we don't do it in encode_def_ids.
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
} else { } else {
record!(self.tables.children[def_id] <- iter_from_generator(|| { record_array!(self.tables.children[def_id] <- iter_from_generator(|| {
for item_id in md.item_ids { for item_id in md.item_ids {
match tcx.hir().item(*item_id).kind { match tcx.hir().item(*item_id).kind {
// Foreign items are planted into their parent modules // Foreign items are planted into their parent modules
@ -1156,7 +1154,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id); let bounds = self.tcx.explicit_item_bounds(def_id);
if !bounds.is_empty() { if !bounds.is_empty() {
record!(self.tables.explicit_item_bounds[def_id] <- bounds); record_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
} }
} }
@ -1188,10 +1186,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() }; let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
match *m { match *m {
hir::TraitFn::Required(ref names) => { hir::TraitFn::Required(ref names) => {
record!(self.tables.fn_arg_names[def_id] <- *names) record_array!(self.tables.fn_arg_names[def_id] <- *names)
} }
hir::TraitFn::Provided(body) => { hir::TraitFn::Provided(body) => {
record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)) record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
} }
}; };
self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
@ -1253,7 +1251,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
self.tables.asyncness.set(def_id.index, sig.header.asyncness); self.tables.asyncness.set(def_id.index, sig.header.asyncness);
record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
let constness = if self.tcx.is_const_fn_raw(def_id) { let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const hir::Constness::Const
@ -1385,7 +1383,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
hir::ItemKind::Fn(ref sig, .., body) => { hir::ItemKind::Fn(ref sig, .., body) => {
self.tables.asyncness.set(def_id.index, sig.header.asyncness); self.tables.asyncness.set(def_id.index, sig.header.asyncness);
record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
self.tables.impl_constness.set(def_id.index, sig.header.constness); self.tables.impl_constness.set(def_id.index, sig.header.constness);
EntryKind::Fn EntryKind::Fn
} }
@ -1485,14 +1483,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.kind[def_id] <- entry_kind); record!(self.tables.kind[def_id] <- entry_kind);
// FIXME(eddyb) there should be a nicer way to do this. // FIXME(eddyb) there should be a nicer way to do this.
match item.kind { match item.kind {
hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <- hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <-
self.tcx.adt_def(def_id).variants().iter().map(|v| { self.tcx.adt_def(def_id).variants().iter().map(|v| {
assert!(v.def_id.is_local()); assert!(v.def_id.is_local());
v.def_id.index v.def_id.index
}) })
), ),
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
record!(self.tables.children[def_id] <- record_array!(self.tables.children[def_id] <-
self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
assert!(f.did.is_local()); assert!(f.did.is_local());
f.did.index f.did.index
@ -1501,7 +1499,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => { hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
record!(self.tables.children[def_id] <- record_array!(self.tables.children[def_id] <-
associated_item_def_ids.iter().map(|&def_id| { associated_item_def_ids.iter().map(|&def_id| {
assert!(def_id.is_local()); assert!(def_id.is_local());
def_id.index def_id.index
@ -1583,16 +1581,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.encode_item_type(def_id.to_def_id()); self.encode_item_type(def_id.to_def_id());
} }
fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> { fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
empty_proc_macro!(self); empty_proc_macro!(self);
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
self.lazy(used_libraries.iter()) self.lazy_array(used_libraries.iter())
} }
fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {
empty_proc_macro!(self); empty_proc_macro!(self);
let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned()) self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
} }
fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) { fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
@ -1631,7 +1629,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index; let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
let stability = tcx.lookup_stability(CRATE_DEF_ID); let stability = tcx.lookup_stability(CRATE_DEF_ID);
let macros = let macros =
self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
for (i, span) in spans.into_iter().enumerate() { for (i, span) in spans.into_iter().enumerate() {
let span = self.lazy(span); let span = self.lazy(span);
@ -1697,12 +1695,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
} }
fn encode_debugger_visualizers(&mut self) -> Lazy<[DebuggerVisualizerFile]> { fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
empty_proc_macro!(self); empty_proc_macro!(self);
self.lazy(self.tcx.debugger_visualizers(LOCAL_CRATE).iter()) self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
} }
fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
empty_proc_macro!(self); empty_proc_macro!(self);
let deps = self let deps = self
@ -1734,29 +1732,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// the assumption that they are numbered 1 to n. // the assumption that they are numbered 1 to n.
// FIXME (#2166): This is not nearly enough to support correct versioning // FIXME (#2166): This is not nearly enough to support correct versioning
// but is enough to get transitive crate dependencies working. // but is enough to get transitive crate dependencies working.
self.lazy(deps.iter().map(|&(_, ref dep)| dep)) self.lazy_array(deps.iter().map(|&(_, ref dep)| dep))
} }
fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> { fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
let lib_features = tcx.lib_features(()); let lib_features = tcx.lib_features(());
self.lazy(lib_features.to_vec()) self.lazy_array(lib_features.to_vec())
} }
fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> { fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id; let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id;
self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index))) self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
} }
fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, usize)> {
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
let lang_items = tcx.lang_items(); let lang_items = tcx.lang_items();
let lang_items = lang_items.items().iter(); let lang_items = lang_items.items().iter();
self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { self.lazy_array(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
if let Some(def_id) = opt_def_id { if let Some(def_id) = opt_def_id {
if def_id.is_local() { if def_id.is_local() {
return Some((def_id.index, i)); return Some((def_id.index, i));
@ -1766,19 +1764,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
})) }))
} }
fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> { fn encode_lang_items_missing(&mut self) -> LazyArray<lang_items::LangItem> {
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
self.lazy(&tcx.lang_items().missing) self.lazy_array(&tcx.lang_items().missing)
} }
fn encode_traits(&mut self) -> Lazy<[DefIndex]> { fn encode_traits(&mut self) -> LazyArray<DefIndex> {
empty_proc_macro!(self); empty_proc_macro!(self);
self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index)) self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
} }
/// Encodes an index, mapping each trait to its (local) implementations. /// Encodes an index, mapping each trait to its (local) implementations.
fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
debug!("EncodeContext::encode_traits_and_impls()"); debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
@ -1817,15 +1815,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
TraitImpls { TraitImpls {
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
impls: self.lazy(&impls), impls: self.lazy_array(&impls),
} }
}) })
.collect(); .collect();
self.lazy(&all_impls) self.lazy_array(&all_impls)
} }
fn encode_incoherent_impls(&mut self) -> Lazy<[IncoherentImpls]> { fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
debug!("EncodeContext::encode_traits_and_impls()"); debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self); empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
@ -1845,11 +1843,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
tcx.hir().def_path_hash(LocalDefId { local_def_index }) tcx.hir().def_path_hash(LocalDefId { local_def_index })
}); });
IncoherentImpls { self_ty: simp, impls: self.lazy(impls) } IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
}) })
.collect(); .collect();
self.lazy(&all_impls) self.lazy_array(&all_impls)
} }
// Encodes all symbols exported from this crate into the metadata. // Encodes all symbols exported from this crate into the metadata.
@ -1861,13 +1859,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_exported_symbols( fn encode_exported_symbols(
&mut self, &mut self,
exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)], exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)],
) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportInfo)]> { ) -> LazyArray<(ExportedSymbol<'tcx>, SymbolExportInfo)> {
empty_proc_macro!(self); empty_proc_macro!(self);
// The metadata symbol name is special. It should not show up in // The metadata symbol name is special. It should not show up in
// downstream crates. // downstream crates.
let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx)); let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
self.lazy( self.lazy_array(
exported_symbols exported_symbols
.iter() .iter()
.filter(|&&(ref exported_symbol, _)| match *exported_symbol { .filter(|&&(ref exported_symbol, _)| match *exported_symbol {
@ -1878,21 +1876,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
) )
} }
fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> { fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
empty_proc_macro!(self); empty_proc_macro!(self);
let formats = self.tcx.dependency_formats(()); let formats = self.tcx.dependency_formats(());
for (ty, arr) in formats.iter() { for (ty, arr) in formats.iter() {
if *ty != CrateType::Dylib { if *ty != CrateType::Dylib {
continue; continue;
} }
return self.lazy(arr.iter().map(|slot| match *slot { return self.lazy_array(arr.iter().map(|slot| match *slot {
Linkage::NotLinked | Linkage::IncludedFromDylib => None, Linkage::NotLinked | Linkage::IncludedFromDylib => None,
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
Linkage::Static => Some(LinkagePreference::RequireStatic), Linkage::Static => Some(LinkagePreference::RequireStatic),
})); }));
} }
Lazy::empty() LazyArray::empty()
} }
fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) { fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
@ -1903,7 +1901,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match nitem.kind { match nitem.kind {
hir::ForeignItemKind::Fn(_, ref names, _) => { hir::ForeignItemKind::Fn(_, ref names, _) => {
self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync); self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync);
record!(self.tables.fn_arg_names[def_id] <- *names); record_array!(self.tables.fn_arg_names[def_id] <- *names);
let constness = if self.tcx.is_const_fn_raw(def_id) { let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const hir::Constness::Const
} else { } else {

View File

@ -1,7 +1,7 @@
use crate::creader::CrateMetadataRef; use crate::creader::CrateMetadataRef;
use decoder::Metadata; use decoder::Metadata;
use def_path_hash_map::DefPathHashMapRef; use def_path_hash_map::DefPathHashMapRef;
use table::{Table, TableBuilder}; use table::TableBuilder;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
@ -20,8 +20,8 @@ use rustc_middle::mir;
use rustc_middle::thir; use rustc_middle::thir;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_middle::ty::{GeneratorDiagnosticData, TyCtxt};
use rustc_serialize::opaque::Encoder; use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion; use rustc_session::config::SymbolManglingVersion;
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@ -62,20 +62,6 @@ const METADATA_VERSION: u8 = 6;
/// and further followed by the rustc version string. /// and further followed by the rustc version string.
pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
/// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
trait LazyMeta {
type Meta: Copy + 'static;
}
impl<T> LazyMeta for T {
type Meta = ();
}
impl<T> LazyMeta for [T] {
type Meta = usize;
}
/// A value of type T referred to by its absolute position /// A value of type T referred to by its absolute position
/// in the metadata, and which can be decoded lazily. /// in the metadata, and which can be decoded lazily.
/// ///
@ -91,8 +77,19 @@ impl<T> LazyMeta for [T] {
/// Distances start at 1, as 0-byte nodes are invalid. /// Distances start at 1, as 0-byte nodes are invalid.
/// Also invalid are nodes being referred in a different /// Also invalid are nodes being referred in a different
/// order than they were encoded in. /// order than they were encoded in.
/// #[must_use]
/// # Sequences (`Lazy<[T]>`) struct LazyValue<T> {
position: NonZeroUsize,
_marker: PhantomData<fn() -> T>,
}
impl<T> LazyValue<T> {
fn from_position(position: NonZeroUsize) -> LazyValue<T> {
LazyValue { position, _marker: PhantomData }
}
}
/// A list of lazily-decoded values.
/// ///
/// Unlike `Lazy<Vec<T>>`, the length is encoded next to the /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
/// position, not at the position, which means that the length /// position, not at the position, which means that the length
@ -102,39 +99,58 @@ impl<T> LazyMeta for [T] {
/// the encoding is that of `Lazy`, with the distinction that /// the encoding is that of `Lazy`, with the distinction that
/// the minimal distance the length of the sequence, i.e. /// the minimal distance the length of the sequence, i.e.
/// it's assumed there's no 0-byte element in the sequence. /// it's assumed there's no 0-byte element in the sequence.
#[must_use] struct LazyArray<T> {
// FIXME(#59875) the `Meta` parameter only exists to dodge
// invariance wrt `T` (coming from the `meta: T::Meta` field).
struct Lazy<T, Meta = <T as LazyMeta>::Meta>
where
T: ?Sized + LazyMeta<Meta = Meta>,
Meta: 'static + Copy,
{
position: NonZeroUsize, position: NonZeroUsize,
meta: Meta, num_elems: usize,
_marker: PhantomData<T>, _marker: PhantomData<fn() -> T>,
} }
impl<T: ?Sized + LazyMeta> Lazy<T> { impl<T> LazyArray<T> {
fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy<T> { fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray<T> {
Lazy { position, meta, _marker: PhantomData } LazyArray { position, num_elems, _marker: PhantomData }
}
fn empty() -> LazyArray<T> {
LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
} }
} }
impl<T> Lazy<T> { /// A list of lazily-decoded values, with the added capability of random access.
fn from_position(position: NonZeroUsize) -> Lazy<T> { ///
Lazy::from_position_and_meta(position, ()) /// Random-access table (i.e. offering constant-time `get`/`set`), similar to
/// `LazyArray<T>`, but without requiring encoding or decoding all the values
/// eagerly and in-order.
struct LazyTable<I, T> {
position: NonZeroUsize,
encoded_size: usize,
_marker: PhantomData<fn(I) -> T>,
}
impl<I, T> LazyTable<I, T> {
fn from_position_and_encoded_size(
position: NonZeroUsize,
encoded_size: usize,
) -> LazyTable<I, T> {
LazyTable { position, encoded_size, _marker: PhantomData }
} }
} }
impl<T> Lazy<[T]> { impl<T> Copy for LazyValue<T> {}
fn empty() -> Lazy<[T]> { impl<T> Clone for LazyValue<T> {
Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) fn clone(&self) -> Self {
*self
} }
} }
impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {} impl<T> Copy for LazyArray<T> {}
impl<T: ?Sized + LazyMeta> Clone for Lazy<T> { impl<T> Clone for LazyArray<T> {
fn clone(&self) -> Self {
*self
}
}
impl<I, T> Copy for LazyTable<I, T> {}
impl<I, T> Clone for LazyTable<I, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
@ -155,29 +171,20 @@ enum LazyState {
Previous(NonZeroUsize), Previous(NonZeroUsize),
} }
// FIXME(#59875) `Lazy!(T)` replaces `Lazy<T>`, passing the `Meta` parameter type SyntaxContextTable = LazyTable<u32, LazyValue<SyntaxContextData>>;
// manually, instead of relying on the default, to get the correct variance. type ExpnDataTable = LazyTable<ExpnIndex, LazyValue<ExpnData>>;
// Only needed when `T` itself contains a parameter (e.g. `'tcx`). type ExpnHashTable = LazyTable<ExpnIndex, LazyValue<ExpnHash>>;
macro_rules! Lazy {
(Table<$I:ty, $T:ty>) => {Lazy<Table<$I, $T>, usize>};
([$T:ty]) => {Lazy<[$T], usize>};
($T:ty) => {Lazy<$T, ()>};
}
type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
type ExpnDataTable = Lazy<Table<ExpnIndex, Lazy<ExpnData>>>;
type ExpnHashTable = Lazy<Table<ExpnIndex, Lazy<ExpnHash>>>;
#[derive(MetadataEncodable, MetadataDecodable)] #[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct ProcMacroData { pub(crate) struct ProcMacroData {
proc_macro_decls_static: DefIndex, proc_macro_decls_static: DefIndex,
stability: Option<attr::Stability>, stability: Option<attr::Stability>,
macros: Lazy<[DefIndex]>, macros: LazyArray<DefIndex>,
} }
/// Serialized metadata for a crate. /// Serialized metadata for a crate.
/// When compiling a proc-macro crate, we encode many of /// When compiling a proc-macro crate, we encode many of
/// the `Lazy<[T]>` fields as `Lazy::empty()`. This serves two purposes: /// the `LazyArray<T>` fields as `Lazy::empty()`. This serves two purposes:
/// ///
/// 1. We avoid performing unnecessary work. Proc-macro crates can only /// 1. We avoid performing unnecessary work. Proc-macro crates can only
/// export proc-macros functions, which are compiled into a shared library. /// export proc-macros functions, which are compiled into a shared library.
@ -205,32 +212,32 @@ pub(crate) struct CrateRoot<'tcx> {
has_panic_handler: bool, has_panic_handler: bool,
has_default_lib_allocator: bool, has_default_lib_allocator: bool,
crate_deps: Lazy<[CrateDep]>, crate_deps: LazyArray<CrateDep>,
dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>, dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
lib_features: Lazy<[(Symbol, Option<Symbol>)]>, lib_features: LazyArray<(Symbol, Option<Symbol>)>,
lang_items: Lazy<[(DefIndex, usize)]>, lang_items: LazyArray<(DefIndex, usize)>,
lang_items_missing: Lazy<[lang_items::LangItem]>, lang_items_missing: LazyArray<lang_items::LangItem>,
diagnostic_items: Lazy<[(Symbol, DefIndex)]>, diagnostic_items: LazyArray<(Symbol, DefIndex)>,
native_libraries: Lazy<[NativeLib]>, native_libraries: LazyArray<NativeLib>,
foreign_modules: Lazy<[ForeignModule]>, foreign_modules: LazyArray<ForeignModule>,
traits: Lazy<[DefIndex]>, traits: LazyArray<DefIndex>,
impls: Lazy<[TraitImpls]>, impls: LazyArray<TraitImpls>,
incoherent_impls: Lazy<[IncoherentImpls]>, incoherent_impls: LazyArray<IncoherentImpls>,
interpret_alloc_index: Lazy<[u32]>, interpret_alloc_index: LazyArray<u32>,
proc_macro_data: Option<ProcMacroData>, proc_macro_data: Option<ProcMacroData>,
tables: LazyTables<'tcx>, tables: LazyTables<'tcx>,
debugger_visualizers: Lazy<[rustc_span::DebuggerVisualizerFile]>, debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>,
exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportInfo)]), exported_symbols: LazyArray<(ExportedSymbol<'tcx>, SymbolExportInfo)>,
syntax_contexts: SyntaxContextTable, syntax_contexts: SyntaxContextTable,
expn_data: ExpnDataTable, expn_data: ExpnDataTable,
expn_hashes: ExpnHashTable, expn_hashes: ExpnHashTable,
def_path_hash_map: Lazy<DefPathHashMapRef<'tcx>>, def_path_hash_map: LazyValue<DefPathHashMapRef<'tcx>>,
source_map: Lazy<[rustc_span::SourceFile]>, source_map: LazyArray<rustc_span::SourceFile>,
compiler_builtins: bool, compiler_builtins: bool,
needs_allocator: bool, needs_allocator: bool,
@ -257,7 +264,12 @@ impl Into<RawDefId> for DefId {
} }
impl RawDefId { impl RawDefId {
fn decode(self, cdata: CrateMetadataRef<'_>) -> DefId { /// This exists so that `provide_one!` is happy
fn decode(self, meta: (CrateMetadataRef<'_>, TyCtxt<'_>)) -> DefId {
self.decode_from_cdata(meta.0)
}
fn decode_from_cdata(self, cdata: CrateMetadataRef<'_>) -> DefId {
let krate = CrateNum::from_u32(self.krate); let krate = CrateNum::from_u32(self.krate);
let krate = cdata.map_encoded_cnum_to_current(krate); let krate = cdata.map_encoded_cnum_to_current(krate);
DefId { krate, index: DefIndex::from_u32(self.index) } DefId { krate, index: DefIndex::from_u32(self.index) }
@ -276,13 +288,13 @@ pub(crate) struct CrateDep {
#[derive(MetadataEncodable, MetadataDecodable)] #[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct TraitImpls { pub(crate) struct TraitImpls {
trait_id: (u32, DefIndex), trait_id: (u32, DefIndex),
impls: Lazy<[(DefIndex, Option<SimplifiedType>)]>, impls: LazyArray<(DefIndex, Option<SimplifiedType>)>,
} }
#[derive(MetadataEncodable, MetadataDecodable)] #[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct IncoherentImpls { pub(crate) struct IncoherentImpls {
self_ty: SimplifiedType, self_ty: SimplifiedType,
impls: Lazy<[DefIndex]>, impls: LazyArray<DefIndex>,
} }
/// Define `LazyTables` and `TableBuilders` at the same time. /// Define `LazyTables` and `TableBuilders` at the same time.
@ -290,7 +302,7 @@ macro_rules! define_tables {
($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => { ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
#[derive(MetadataEncodable, MetadataDecodable)] #[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct LazyTables<'tcx> { pub(crate) struct LazyTables<'tcx> {
$($name: Lazy!(Table<$IDX, $T>)),+ $($name: LazyTable<$IDX, $T>),+
} }
#[derive(Default)] #[derive(Default)]
@ -309,61 +321,62 @@ macro_rules! define_tables {
} }
define_tables! { define_tables! {
kind: Table<DefIndex, Lazy<EntryKind>>, kind: Table<DefIndex, LazyValue<EntryKind>>,
attributes: Table<DefIndex, Lazy<[ast::Attribute]>>, attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
children: Table<DefIndex, Lazy<[DefIndex]>>, children: Table<DefIndex, LazyArray<DefIndex>>,
opt_def_kind: Table<DefIndex, DefKind>, opt_def_kind: Table<DefIndex, DefKind>,
visibility: Table<DefIndex, Lazy<ty::Visibility>>, visibility: Table<DefIndex, LazyValue<ty::Visibility>>,
def_span: Table<DefIndex, Lazy<Span>>, def_span: Table<DefIndex, LazyValue<Span>>,
def_ident_span: Table<DefIndex, Lazy<Span>>, def_ident_span: Table<DefIndex, LazyValue<Span>>,
lookup_stability: Table<DefIndex, Lazy<attr::Stability>>, lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
lookup_const_stability: Table<DefIndex, Lazy<attr::ConstStability>>, lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
lookup_deprecation_entry: Table<DefIndex, Lazy<attr::Deprecation>>, lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
// As an optimization, a missing entry indicates an empty `&[]`. // As an optimization, a missing entry indicates an empty `&[]`.
explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>, explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'tcx>, Span)>>,
explicit_predicates_of: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>, explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'tcx>>>,
generics_of: Table<DefIndex, Lazy<ty::Generics>>, generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
// As an optimization, a missing entry indicates an empty `&[]`. // As an optimization, a missing entry indicates an empty `&[]`.
inferred_outlives_of: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>, inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Predicate<'tcx>, Span)>>,
super_predicates_of: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>, super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'tcx>>>,
type_of: Table<DefIndex, Lazy!(Ty<'tcx>)>, type_of: Table<DefIndex, LazyValue<Ty<'tcx>>>,
variances_of: Table<DefIndex, Lazy<[ty::Variance]>>, variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>, fn_sig: Table<DefIndex, LazyValue<ty::PolyFnSig<'tcx>>>,
codegen_fn_attrs: Table<DefIndex, Lazy!(CodegenFnAttrs)>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>, impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'tcx>>>,
const_param_default: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>, const_param_default: Table<DefIndex, LazyValue<rustc_middle::ty::Const<'tcx>>>,
optimized_mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'tcx>>>,
mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>, mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'tcx>>>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'tcx>>>>,
thir_abstract_const: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>, // FIXME(compiler-errors): Why isn't this a LazyArray?
thir_abstract_const: Table<DefIndex, LazyValue<&'tcx [thir::abstract_const::Node<'tcx>]>>,
impl_parent: Table<DefIndex, RawDefId>, impl_parent: Table<DefIndex, RawDefId>,
impl_polarity: Table<DefIndex, ty::ImplPolarity>, impl_polarity: Table<DefIndex, ty::ImplPolarity>,
impl_constness: Table<DefIndex, hir::Constness>, impl_constness: Table<DefIndex, hir::Constness>,
is_intrinsic: Table<DefIndex, ()>, is_intrinsic: Table<DefIndex, ()>,
impl_defaultness: Table<DefIndex, hir::Defaultness>, impl_defaultness: Table<DefIndex, hir::Defaultness>,
// FIXME(eddyb) perhaps compute this on the fly if cheap enough? // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
coerce_unsized_info: Table<DefIndex, Lazy!(ty::adjustment::CoerceUnsizedInfo)>, coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
mir_const_qualif: Table<DefIndex, Lazy!(mir::ConstQualifs)>, mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
rendered_const: Table<DefIndex, Lazy!(String)>, rendered_const: Table<DefIndex, LazyValue<String>>,
asyncness: Table<DefIndex, hir::IsAsync>, asyncness: Table<DefIndex, hir::IsAsync>,
fn_arg_names: Table<DefIndex, Lazy!([Ident])>, fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
generator_kind: Table<DefIndex, Lazy!(hir::GeneratorKind)>, generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
trait_def: Table<DefIndex, Lazy!(ty::TraitDef)>, trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
trait_item_def_id: Table<DefIndex, RawDefId>, trait_item_def_id: Table<DefIndex, RawDefId>,
inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>, expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>, unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>,
repr_options: Table<DefIndex, Lazy<ReprOptions>>, repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
// `def_keys` and `def_path_hashes` represent a lazy version of a // `def_keys` and `def_path_hashes` represent a lazy version of a
// `DefPathTable`. This allows us to avoid deserializing an entire // `DefPathTable`. This allows us to avoid deserializing an entire
// `DefPathTable` up front, since we may only ever use a few // `DefPathTable` up front, since we may only ever use a few
// definitions from any given crate. // definitions from any given crate.
def_keys: Table<DefIndex, Lazy<DefKey>>, def_keys: Table<DefIndex, LazyValue<DefKey>>,
def_path_hashes: Table<DefIndex, DefPathHash>, def_path_hashes: Table<DefIndex, DefPathHash>,
proc_macro_quoted_spans: Table<usize, Lazy<Span>>, proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>, generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'tcx>>>,
may_have_doc_links: Table<DefIndex, ()>, may_have_doc_links: Table<DefIndex, ()>,
} }
@ -382,19 +395,19 @@ enum EntryKind {
OpaqueTy, OpaqueTy,
Enum, Enum,
Field, Field,
Variant(Lazy<VariantData>), Variant(LazyValue<VariantData>),
Struct(Lazy<VariantData>), Struct(LazyValue<VariantData>),
Union(Lazy<VariantData>), Union(LazyValue<VariantData>),
Fn, Fn,
ForeignFn, ForeignFn,
Mod(Lazy<[ModChild]>), Mod(LazyArray<ModChild>),
MacroDef(Lazy<ast::MacArgs>, /*macro_rules*/ bool), MacroDef(LazyValue<ast::MacArgs>, /*macro_rules*/ bool),
ProcMacro(MacroKind), ProcMacro(MacroKind),
Closure, Closure,
Generator, Generator,
Trait, Trait,
Impl, Impl,
AssocFn(Lazy<AssocFnData>), AssocFn(LazyValue<AssocFnData>),
AssocType(AssocContainer), AssocType(AssocContainer),
AssocConst(AssocContainer), AssocConst(AssocContainer),
TraitAlias, TraitAlias,

View File

@ -201,15 +201,15 @@ impl FixedSizeEncoding for Option<()> {
} }
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
// generic `Lazy<T>` impl, but in the general case we might not need / want to // generic `LazyValue<T>` impl, but in the general case we might not need / want
// fit every `usize` in `u32`. // to fit every `usize` in `u32`.
impl<T> FixedSizeEncoding for Option<Lazy<T>> { impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
type ByteArray = [u8; 4]; type ByteArray = [u8; 4];
#[inline] #[inline]
fn from_bytes(b: &[u8; 4]) -> Self { fn from_bytes(b: &[u8; 4]) -> Self {
let position = NonZeroUsize::new(u32::from_bytes(b) as usize)?; let position = NonZeroUsize::new(u32::from_bytes(b) as usize)?;
Some(Lazy::from_position(position)) Some(LazyValue::from_position(position))
} }
#[inline] #[inline]
@ -220,7 +220,7 @@ impl<T> FixedSizeEncoding for Option<Lazy<T>> {
} }
} }
impl<T> FixedSizeEncoding for Option<Lazy<[T]>> { impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
type ByteArray = [u8; 8]; type ByteArray = [u8; 8];
#[inline] #[inline]
@ -228,7 +228,7 @@ impl<T> FixedSizeEncoding for Option<Lazy<[T]>> {
let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() }; let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?; let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
let len = u32::from_bytes(meta_bytes) as usize; let len = u32::from_bytes(meta_bytes) as usize;
Some(Lazy::from_position_and_meta(position, len)) Some(LazyArray::from_position_and_num_elems(position, len))
} }
#[inline] #[inline]
@ -239,28 +239,12 @@ impl<T> FixedSizeEncoding for Option<Lazy<[T]>> {
let position: u32 = position.try_into().unwrap(); let position: u32 = position.try_into().unwrap();
position.write_to_bytes(position_bytes); position.write_to_bytes(position_bytes);
let len = self.map_or(0, |lazy| lazy.meta); let len = self.map_or(0, |lazy| lazy.num_elems);
let len: u32 = len.try_into().unwrap(); let len: u32 = len.try_into().unwrap();
len.write_to_bytes(meta_bytes); len.write_to_bytes(meta_bytes);
} }
} }
/// Random-access table (i.e. offering constant-time `get`/`set`), similar to
/// `Vec<Option<T>>`, but without requiring encoding or decoding all the values
/// eagerly and in-order.
/// A total of `(max_idx + 1)` times `Option<T> as FixedSizeEncoding>::ByteArray`
/// are used for a table, where `max_idx` is the largest index passed to
/// `TableBuilder::set`.
pub(super) struct Table<I: Idx, T>
where
Option<T>: FixedSizeEncoding,
{
_marker: PhantomData<(fn(&I), T)>,
// NOTE(eddyb) this makes `Table` not implement `Sized`, but no
// value of `Table` is ever created (it's always behind `Lazy`).
_bytes: [u8],
}
/// Helper for constructing a table's serialization (also see `Table`). /// Helper for constructing a table's serialization (also see `Table`).
pub(super) struct TableBuilder<I: Idx, T> pub(super) struct TableBuilder<I: Idx, T>
where where
@ -296,7 +280,7 @@ where
Some(value).write_to_bytes(&mut self.blocks[i]); Some(value).write_to_bytes(&mut self.blocks[i]);
} }
pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> LazyTable<I, T>
where where
Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>, Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{ {
@ -305,19 +289,14 @@ where
buf.emit_raw_bytes(block).unwrap(); buf.emit_raw_bytes(block).unwrap();
} }
let num_bytes = self.blocks.len() * N; let num_bytes = self.blocks.len() * N;
Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), num_bytes) LazyTable::from_position_and_encoded_size(
NonZeroUsize::new(pos as usize).unwrap(),
num_bytes,
)
} }
} }
impl<I: Idx, T> LazyMeta for Table<I, T> impl<I: Idx, T> LazyTable<I, T>
where
Option<T>: FixedSizeEncoding,
{
/// Number of bytes in the data stream.
type Meta = usize;
}
impl<I: Idx, T> Lazy<Table<I, T>>
where where
Option<T>: FixedSizeEncoding, Option<T>: FixedSizeEncoding,
{ {
@ -331,10 +310,10 @@ where
where where
Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>, Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{ {
debug!("Table::lookup: index={:?} len={:?}", i, self.meta); debug!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
let start = self.position.get(); let start = self.position.get();
let bytes = &metadata.blob()[start..start + self.meta]; let bytes = &metadata.blob()[start..start + self.encoded_size];
let (bytes, []) = bytes.as_chunks::<N>() else { panic!() }; let (bytes, []) = bytes.as_chunks::<N>() else { panic!() };
let bytes = bytes.get(i.index())?; let bytes = bytes.get(i.index())?;
FixedSizeEncoding::from_bytes(bytes) FixedSizeEncoding::from_bytes(bytes)
@ -345,6 +324,6 @@ where
where where
Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>, Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{ {
self.meta / N self.encoded_size / N
} }
} }