rust/compiler/rustc_query_impl/src/on_disk_cache.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1087 lines
40 KiB
Rust
Raw Normal View History

2021-06-28 19:12:01 +00:00
use crate::QueryCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
use rustc_data_structures::unhash::UnhashMap;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
2021-06-28 19:12:01 +00:00
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, interpret};
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
use rustc_serialize::{
opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
Decodable, Decoder, Encodable, Encoder,
};
use rustc_session::Session;
2020-03-17 15:45:02 +00:00
use rustc_span::hygiene::{
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
2020-03-17 15:45:02 +00:00
};
use rustc_span::source_map::{SourceMap, StableSourceFileId};
2021-04-18 12:27:28 +00:00
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
use rustc_span::{CachingSourceMapView, Symbol};
use std::collections::hash_map::Entry;
use std::io;
use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
// A normal span encoded with both location information and a `SyntaxContext`
const TAG_FULL_SPAN: u8 = 0;
// A partial span with no location information, encoded only with a `SyntaxContext`
const TAG_PARTIAL_SPAN: u8 = 1;
2021-04-18 12:27:28 +00:00
const TAG_RELATIVE_SPAN: u8 = 2;
2020-03-17 15:45:02 +00:00
const TAG_SYNTAX_CONTEXT: u8 = 0;
const TAG_EXPN_DATA: u8 = 1;
// Tags for encoding Symbol's
const SYMBOL_STR: u8 = 0;
const SYMBOL_OFFSET: u8 = 1;
const SYMBOL_PREINTERNED: u8 = 2;
/// Provides an interface to incremental compilation data cached from the
/// previous compilation session. This data will eventually include the results
2020-07-17 08:47:04 +00:00
/// of a few selected queries (like `typeck` and `mir_optimized`) and
/// any side effects that have been emitted during a query.
pub struct OnDiskCache<'sess> {
// The complete cache data in serialized form.
serialized_data: RwLock<Option<Mmap>>,
// Collects all `QuerySideEffects` created during the current compilation
// session.
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
2018-08-18 10:14:14 +00:00
source_map: &'sess SourceMap,
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
// Caches that are populated lazily during decoding.
2018-08-18 10:13:52 +00:00
file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
// A map from dep-node to the position of the cached query result in
// `serialized_data`.
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
// A map from dep-node to the position of any associated `QuerySideEffects` in
// `serialized_data`.
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
alloc_decoding_state: AllocDecodingState,
2020-03-17 15:45:02 +00:00
// A map from syntax context ids to the position of their associated
// `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
// to represent the fact that we are storing *encoded* ids. When we decode
// a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
// which will almost certainly be different than the serialized id.
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
// A map from the `DefPathHash` of an `ExpnId` to the position
// of their associated `ExpnData`. Ideally, we would store a `DefId`,
// but we need to decode this before we've constructed a `TyCtxt` (which
// makes it difficult to decode a `DefId`).
// Note that these `DefPathHashes` correspond to both local and foreign
// `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
// we could look up the `ExpnData` from the metadata of foreign crates,
// but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
2020-03-17 15:45:02 +00:00
// Additional information used when decoding hygiene data.
hygiene_context: HygieneDecodeContext,
// Maps `ExpnHash`es to their raw value from the *previous*
// compilation session. This is used as an initial 'guess' when
// we try to map an `ExpnHash` to its value in the current
// compilation session.
foreign_expn_data: UnhashMap<ExpnHash, u32>,
}
2020-03-17 15:45:02 +00:00
// This type is used only for serialization and deserialization.
#[derive(Encodable, Decodable)]
struct Footer {
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
query_result_index: EncodedDepNodeIndex,
side_effects_index: EncodedDepNodeIndex,
// The location of all allocations.
interpret_alloc_index: Vec<u32>,
2020-03-17 15:45:02 +00:00
// See `OnDiskCache.syntax_contexts`
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
// See `OnDiskCache.expn_data`
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
foreign_expn_data: UnhashMap<ExpnHash, u32>,
}
pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
2018-08-18 10:13:52 +00:00
struct SourceFileIndex(u32);
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
2020-10-11 08:34:13 +00:00
pub struct AbsoluteBytePos(u32);
impl AbsoluteBytePos {
fn new(pos: usize) -> AbsoluteBytePos {
2020-03-04 12:18:08 +00:00
debug_assert!(pos <= u32::MAX as usize);
AbsoluteBytePos(pos as u32)
}
fn to_usize(self) -> usize {
self.0 as usize
}
}
/// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that
/// the source crate is represented as a [StableCrateId] instead of as a
/// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded
/// without any additional context, i.e. with a simple `opaque::Decoder` (which
/// is the only thing available when decoding the cache's [Footer].
#[derive(Encodable, Decodable, Clone, Debug)]
struct EncodedSourceFileId {
file_name_hash: u64,
stable_crate_id: StableCrateId,
}
impl EncodedSourceFileId {
fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId {
let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id);
StableSourceFileId { file_name_hash: self.file_name_hash, cnum }
}
fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId {
let source_file_id = StableSourceFileId::new(file);
EncodedSourceFileId {
file_name_hash: source_file_id.file_name_hash,
stable_crate_id: tcx.stable_crate_id(source_file_id.cnum),
}
}
}
2021-06-28 19:12:01 +00:00
impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
debug_assert!(sess.opts.incremental.is_some());
// Wrap in a scope so we can borrow `data`.
let footer: Footer = {
let mut decoder = MemDecoder::new(&data, start_pos);
// Decode the *position* of the footer, which can be found in the
// last 8 bytes of the file.
decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
2022-01-18 02:22:50 +00:00
let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder).0 as usize;
// Decode the file footer, which contains all the lookup tables, etc.
decoder.set_position(footer_pos);
2020-03-17 15:45:02 +00:00
decode_tagged(&mut decoder, TAG_FILE_FOOTER)
};
Self {
serialized_data: RwLock::new(Some(data)),
file_index_to_stable_id: footer.file_index_to_stable_id,
file_index_to_file: Default::default(),
2018-08-18 10:14:14 +00:00
source_map: sess.source_map(),
current_side_effects: Default::default(),
query_result_index: footer.query_result_index.into_iter().collect(),
prev_side_effects_index: footer.side_effects_index.into_iter().collect(),
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
2020-03-17 15:45:02 +00:00
syntax_contexts: footer.syntax_contexts,
expn_data: footer.expn_data,
foreign_expn_data: footer.foreign_expn_data,
hygiene_context: Default::default(),
}
}
2021-06-28 19:12:01 +00:00
fn new_empty(source_map: &'sess SourceMap) -> Self {
Self {
serialized_data: RwLock::new(None),
file_index_to_stable_id: Default::default(),
file_index_to_file: Default::default(),
2018-08-18 10:14:14 +00:00
source_map,
current_side_effects: Default::default(),
query_result_index: Default::default(),
prev_side_effects_index: Default::default(),
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
2020-03-17 15:45:02 +00:00
syntax_contexts: FxHashMap::default(),
expn_data: UnhashMap::default(),
foreign_expn_data: UnhashMap::default(),
hygiene_context: Default::default(),
}
}
2021-08-28 19:49:51 +00:00
/// Execute all cache promotions and release the serialized backing Mmap.
///
/// Cache promotions require invoking queries, which needs to read the serialized data.
/// In order to serialize the new on-disk cache, the former on-disk cache file needs to be
/// deleted, hence we won't be able to refer to its memmapped data.
fn drop_serialized_data(&self, tcx: TyCtxt<'_>) {
// Load everything into memory so we can write it out to the on-disk
// cache. The vast majority of cacheable query results should already
// be in memory, so this should be a cheap operation.
// Do this *before* we clone 'latest_foreign_def_path_hashes', since
// loading existing queries may cause us to create new DepNodes, which
// may in turn end up invoking `store_foreign_def_id_hash`
2021-10-16 18:24:08 +00:00
tcx.dep_graph.exec_cache_promotions(tcx);
*self.serialized_data.write() = None;
}
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult {
// Serializing the `DepGraph` should not modify it.
tcx.dep_graph.with_ignore(|| {
// Allocate `SourceFileIndex`es.
let (file_to_file_index, file_index_to_stable_id) = {
let files = tcx.sess.source_map().files();
let mut file_to_file_index =
FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
let mut file_index_to_stable_id =
FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
for (index, file) in files.iter().enumerate() {
2018-08-18 10:13:52 +00:00
let index = SourceFileIndex(index as u32);
let file_ptr: *const SourceFile = &**file as *const _;
file_to_file_index.insert(file_ptr, index);
let source_file_id = EncodedSourceFileId::new(tcx, &file);
file_index_to_stable_id.insert(index, source_file_id);
}
(file_to_file_index, file_index_to_stable_id)
};
let hygiene_encode_context = HygieneEncodeContext::default();
let mut encoder = CacheEncoder {
tcx,
encoder,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
interpret_allocs: Default::default(),
source_map: CachingSourceMapView::new(tcx.sess.source_map()),
file_to_file_index,
hygiene_context: &hygiene_encode_context,
symbol_table: Default::default(),
};
// Encode query results.
let mut query_result_index = EncodedDepNodeIndex::new();
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
tcx.sess.time("encode_query_results", || {
let enc = &mut encoder;
let qri = &mut query_result_index;
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri);
});
2018-03-09 06:09:24 +00:00
// Encode side effects.
let side_effects_index: EncodedDepNodeIndex = self
.current_side_effects
2018-10-01 13:39:17 +00:00
.borrow()
.iter()
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
.map(|(dep_node_index, side_effects)| {
let pos = AbsoluteBytePos::new(encoder.position());
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
encoder.encode_tagged(dep_node_index, side_effects);
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
(dep_node_index, pos)
})
.collect();
let interpret_alloc_index = {
let mut interpret_alloc_index = Vec::new();
let mut n = 0;
loop {
let new_n = encoder.interpret_allocs.len();
// If we have found new IDs, serialize those too.
2018-04-13 16:48:41 +00:00
if n == new_n {
// Otherwise, abort.
2018-04-13 16:48:41 +00:00
break;
}
2018-11-05 14:30:04 +00:00
interpret_alloc_index.reserve(new_n - n);
for idx in n..new_n {
let id = encoder.interpret_allocs[idx];
let pos = encoder.position() as u32;
interpret_alloc_index.push(pos);
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
interpret::specialized_encode_alloc_id(&mut encoder, tcx, id);
}
n = new_n;
}
interpret_alloc_index
};
2020-03-17 15:45:02 +00:00
let mut syntax_contexts = FxHashMap::default();
let mut expn_data = UnhashMap::default();
let mut foreign_expn_data = UnhashMap::default();
2020-03-17 15:45:02 +00:00
// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
// session.
hygiene_encode_context.encode(
&mut encoder,
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
|encoder, index, ctxt_data| {
let pos = AbsoluteBytePos::new(encoder.position());
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data);
syntax_contexts.insert(index, pos);
},
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
|encoder, expn_id, data, hash| {
if expn_id.krate == LOCAL_CRATE {
2021-07-10 21:34:41 +00:00
let pos = AbsoluteBytePos::new(encoder.position());
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
encoder.encode_tagged(TAG_EXPN_DATA, data);
expn_data.insert(hash, pos);
} else {
foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
2021-07-10 21:34:41 +00:00
}
},
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
);
2020-03-17 15:45:02 +00:00
// `Encode the file footer.
let footer_pos = encoder.position() as u64;
encoder.encode_tagged(
TAG_FILE_FOOTER,
&Footer {
file_index_to_stable_id,
query_result_index,
side_effects_index,
interpret_alloc_index,
2020-03-17 15:45:02 +00:00
syntax_contexts,
expn_data,
foreign_expn_data,
},
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
);
// Encode the position of the footer as the last 8 bytes of the
// file so we know where to look for it.
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
IntEncodedWithFixedSize(footer_pos).encode(&mut encoder.encoder);
// DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
// of the footer must be the last thing in the data stream.
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
encoder.finish()
})
}
2021-06-28 19:12:01 +00:00
}
impl<'sess> OnDiskCache<'sess> {
pub fn as_dyn(&self) -> &dyn rustc_middle::ty::OnDiskCache<'sess> {
self as _
}
/// Loads a `QuerySideEffects` created during the previous compilation session.
pub fn load_side_effects(
&self,
2019-06-21 21:49:03 +00:00
tcx: TyCtxt<'_>,
dep_node_index: SerializedDepNodeIndex,
) -> QuerySideEffects {
let side_effects: Option<QuerySideEffects> =
2022-01-18 02:22:50 +00:00
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
side_effects.unwrap_or_default()
}
/// Stores a `QuerySideEffects` emitted during the current compilation session.
/// Anything stored like this will be available via `load_side_effects` in
/// the next compilation session.
#[inline(never)]
#[cold]
pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
let mut current_side_effects = self.current_side_effects.borrow_mut();
let prev = current_side_effects.insert(dep_node_index, side_effects);
debug_assert!(prev.is_none());
}
/// Returns the cached query result if there is something in the cache for
2019-02-08 13:53:55 +00:00
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
) -> Option<T>
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
2022-01-18 02:22:50 +00:00
self.load_indexed(tcx, dep_node_index, &self.query_result_index)
}
/// Stores side effect emitted during computation of an anonymous query.
/// Since many anonymous queries can share the same `DepNode`, we aggregate
/// them -- as opposed to regular queries where we assume that there is a
/// 1:1 relationship between query-key and `DepNode`.
#[inline(never)]
#[cold]
pub fn store_side_effects_for_anon_node(
&self,
dep_node_index: DepNodeIndex,
side_effects: QuerySideEffects,
) {
let mut current_side_effects = self.current_side_effects.borrow_mut();
let x = current_side_effects.entry(dep_node_index).or_default();
x.append(side_effects);
}
fn load_indexed<'tcx, T>(
&self,
2019-06-13 21:48:52 +00:00
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
) -> Option<T>
where
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
2018-12-19 12:19:48 +00:00
let pos = index.get(&dep_node_index).cloned()?;
2022-01-18 02:22:50 +00:00
self.with_decoder(tcx, pos, |decoder| Some(decode_tagged(decoder, dep_node_index)))
2020-03-17 15:45:02 +00:00
}
fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(
2020-03-17 15:45:02 +00:00
&'sess self,
tcx: TyCtxt<'tcx>,
pos: AbsoluteBytePos,
f: F,
) -> T
where
T: Decodable<CacheDecoder<'a, 'tcx>>,
2020-03-17 15:45:02 +00:00
{
let serialized_data = self.serialized_data.read();
let mut decoder = CacheDecoder {
tcx,
opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
2018-08-18 10:14:14 +00:00
source_map: self.source_map,
file_index_to_file: &self.file_index_to_file,
file_index_to_stable_id: &self.file_index_to_stable_id,
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
2020-03-17 15:45:02 +00:00
syntax_contexts: &self.syntax_contexts,
expn_data: &self.expn_data,
foreign_expn_data: &self.foreign_expn_data,
2020-03-17 15:45:02 +00:00
hygiene_context: &self.hygiene_context,
};
2020-03-17 15:45:02 +00:00
f(&mut decoder)
}
}
//- DECODING -------------------------------------------------------------------
/// A decoder that can read from the incremental compilation cache. It is similar to the one
/// we use for crate metadata decoding in that it can rebase spans and eventually
/// will also handle things that contain `Ty` instances.
pub struct CacheDecoder<'a, 'tcx> {
2019-06-13 21:48:52 +00:00
tcx: TyCtxt<'tcx>,
opaque: MemDecoder<'a>,
source_map: &'a SourceMap,
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
alloc_decoding_session: AllocDecodingSession<'a>,
2020-03-17 15:45:02 +00:00
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
hygiene_context: &'a HygieneDecodeContext,
}
impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
2018-08-18 10:13:52 +00:00
fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
let CacheDecoder {
tcx,
ref file_index_to_file,
ref file_index_to_stable_id,
2018-08-18 10:14:14 +00:00
ref source_map,
..
} = *self;
file_index_to_file
.borrow_mut()
.entry(index)
.or_insert_with(|| {
let stable_id = file_index_to_stable_id[&index].translate(tcx);
// If this `SourceFile` is from a foreign crate, then make sure
// that we've imported all of the source files from that crate.
// This has usually already been done during macro invocation.
// However, when encoding query results like `TypeckResults`,
// we might encode an `AdtDef` for a foreign type (because it
// was referenced in the body of the function). There is no guarantee
// that we will load the source files from that crate during macro
// expansion, so we use `import_source_files` to ensure that the foreign
// source files are actually imported before we call `source_file_by_stable_id`.
if stable_id.cnum != LOCAL_CRATE {
self.tcx.cstore_untracked().import_source_files(self.tcx.sess, stable_id.cnum);
}
2018-08-18 10:14:14 +00:00
source_map
.source_file_by_stable_id(stable_id)
.expect("failed to lookup `SourceFile` in new context")
})
.clone()
}
}
trait DecoderWithPosition: Decoder {
fn position(&self) -> usize;
}
impl<'a> DecoderWithPosition for MemDecoder<'a> {
fn position(&self) -> usize {
self.position()
}
}
impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> {
fn position(&self) -> usize {
self.opaque.position()
}
}
// Decodes something that was encoded with `encode_tagged()` and verify that the
// tag matches and the correct amount of bytes was read.
2022-01-18 02:22:50 +00:00
fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> V
where
T: Decodable<D> + Eq + std::fmt::Debug,
V: Decodable<D>,
D: DecoderWithPosition,
{
let start_pos = decoder.position();
2022-01-18 02:22:50 +00:00
let actual_tag = T::decode(decoder);
assert_eq!(actual_tag, expected_tag);
2022-01-18 02:22:50 +00:00
let value = V::decode(decoder);
let end_pos = decoder.position();
2022-01-18 02:22:50 +00:00
let expected_len: u64 = Decodable::decode(decoder);
assert_eq!((end_pos - start_pos) as u64, expected_len);
2022-01-18 02:22:50 +00:00
value
}
2021-01-31 09:32:34 +00:00
impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
type I = TyCtxt<'tcx>;
const CLEAR_CROSS_CRATE: bool = false;
#[inline]
fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
#[inline]
fn position(&self) -> usize {
self.opaque.position()
}
#[inline]
fn peek_byte(&self) -> u8 {
self.opaque.data[self.opaque.position()]
}
2022-01-18 02:22:50 +00:00
fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
2019-04-25 20:54:19 +00:00
where
2022-01-18 02:22:50 +00:00
F: FnOnce(&mut Self) -> Ty<'tcx>,
{
2021-01-31 09:32:34 +00:00
let tcx = self.tcx;
let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand };
2020-06-10 08:26:54 +00:00
if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
2022-01-18 02:22:50 +00:00
return ty;
}
2022-01-18 02:22:50 +00:00
let ty = or_insert_with(self);
// This may overwrite the entry, but it should overwrite with the same value.
2020-06-10 08:26:54 +00:00
tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty);
2022-01-18 02:22:50 +00:00
ty
}
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
debug_assert!(pos < self.opaque.data.len());
let new_opaque = MemDecoder::new(self.opaque.data, pos);
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
let r = f(self);
self.opaque = old_opaque;
r
}
2022-01-18 02:22:50 +00:00
fn decode_alloc_id(&mut self) -> interpret::AllocId {
let alloc_decoding_session = self.alloc_decoding_session;
alloc_decoding_session.decode_alloc_id(self)
}
}
2021-06-28 19:12:01 +00:00
rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
Decodable::decode(&mut d.opaque)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
2022-01-18 02:22:50 +00:00
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Self {
let syntax_contexts = decoder.syntax_contexts;
rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
2020-03-17 15:45:02 +00:00
// This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
// We look up the position of the associated `SyntaxData` and decode it.
let pos = syntax_contexts.get(&id).unwrap();
this.with_position(pos.to_usize(), |decoder| {
2022-01-18 02:22:50 +00:00
let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
data
2020-03-17 15:45:02 +00:00
})
})
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
2022-01-18 02:22:50 +00:00
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Self {
let hash = ExpnHash::decode(decoder);
if hash.is_root() {
2022-01-18 02:22:50 +00:00
return ExpnId::root();
}
if let Some(expn_id) = ExpnId::from_hash(hash) {
2022-01-18 02:22:50 +00:00
return expn_id;
}
let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
let expn_id = if krate == LOCAL_CRATE {
// We look up the position of the associated `ExpnData` and decode it.
let pos = decoder
.expn_data
.get(&hash)
.unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));
let data: ExpnData = decoder
2022-01-18 02:22:50 +00:00
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA));
2021-10-02 19:14:52 +00:00
let expn_id = rustc_span::hygiene::register_local_expn_id(data, hash);
#[cfg(debug_assertions)]
{
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
hasher.finish()
2021-10-02 19:14:52 +00:00
});
debug_assert_eq!(hash.local_hash(), local_hash);
}
expn_id
} else {
let index_guess = decoder.foreign_expn_data[&hash];
2021-10-02 15:35:27 +00:00
decoder.tcx.cstore_untracked().expn_hash_to_expn_id(
decoder.tcx.sess,
krate,
index_guess,
hash,
)
};
2021-10-02 19:14:52 +00:00
debug_assert_eq!(expn_id.krate, krate);
2022-01-18 02:22:50 +00:00
expn_id
2020-03-17 15:45:02 +00:00
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
2022-01-18 02:22:50 +00:00
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Self {
let ctxt = SyntaxContext::decode(decoder);
let parent = Option::<LocalDefId>::decode(decoder);
let tag: u8 = Decodable::decode(decoder);
if tag == TAG_PARTIAL_SPAN {
2022-01-18 02:22:50 +00:00
return Span::new(BytePos(0), BytePos(0), ctxt, parent);
2021-04-18 12:27:28 +00:00
} else if tag == TAG_RELATIVE_SPAN {
2022-01-18 02:22:50 +00:00
let dlo = u32::decode(decoder);
let dto = u32::decode(decoder);
2021-04-18 12:27:28 +00:00
let enclosing = decoder.tcx.source_span_untracked(parent.unwrap()).data_untracked();
2021-04-18 12:27:28 +00:00
let span = Span::new(
enclosing.lo + BytePos::from_u32(dlo),
enclosing.lo + BytePos::from_u32(dto),
ctxt,
parent,
);
2022-01-18 02:22:50 +00:00
return span;
} else {
debug_assert_eq!(tag, TAG_FULL_SPAN);
}
2022-01-18 02:22:50 +00:00
let file_lo_index = SourceFileIndex::decode(decoder);
let line_lo = usize::decode(decoder);
let col_lo = BytePos::decode(decoder);
let len = BytePos::decode(decoder);
let file_lo = decoder.file_index_to_file(file_lo_index);
let lo = file_lo.lines(|lines| lines[line_lo - 1] + col_lo);
let hi = lo + len;
2022-01-18 02:22:50 +00:00
Span::new(lo, hi, ctxt, parent)
}
}
// copy&paste impl from rustc_metadata
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
let tag = d.read_u8();
match tag {
SYMBOL_STR => {
let s = d.read_str();
Symbol::intern(s)
}
SYMBOL_OFFSET => {
// read str offset
let pos = d.read_usize();
let old_pos = d.opaque.position();
// move to str ofset and read
d.opaque.set_position(pos);
let s = d.read_str();
let sym = Symbol::intern(s);
// restore position
d.opaque.set_position(old_pos);
sym
}
SYMBOL_PREINTERNED => {
let symbol_index = d.read_u32();
Symbol::new_from_decoded(symbol_index)
}
_ => unreachable!(),
}
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
let stable_id = StableCrateId::decode(d);
let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id);
2022-01-18 02:22:50 +00:00
cnum
}
}
// This impl makes sure that we get a runtime error when we try decode a
// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
// because we would not know how to transform the `DefIndex` to the current
// context.
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
2022-01-18 02:22:50 +00:00
fn decode(_d: &mut CacheDecoder<'a, 'tcx>) -> DefIndex {
panic!("trying to decode `DefIndex` outside the context of a `DefId`")
}
}
// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
// compilation sessions. We use the `DefPathHash`, which is stable across
2019-09-19 05:17:36 +00:00
// sessions, to map the old `DefId` to the new one.
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
// Load the `DefPathHash` which is was we encoded the `DefId` as.
2022-01-18 02:22:50 +00:00
let def_path_hash = DefPathHash::decode(d);
// Using the `DefPathHash`, we can lookup the new `DefId`.
// Subtle: We only encode a `DefId` as part of a query result.
// If we get to this point, then all of the query inputs were green,
// which means that the definition with this hash is guaranteed to
// still exist in the current compilation session.
2021-01-31 09:32:34 +00:00
d.tcx.def_path_hash_to_def_id(def_path_hash, &mut || {
panic!("Failed to convert DefPathHash {:?}", def_path_hash)
2022-01-18 02:22:50 +00:00
})
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
2022-09-09 15:34:11 +00:00
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashMap<DefId, Ty<'tcx>> {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
{
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [ty::abstract_const::Node<'tcx>] {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
2020-04-27 17:56:11 +00:00
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
2022-01-18 02:22:50 +00:00
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
2022-03-28 17:53:01 +00:00
macro_rules! impl_ref_decoder {
(<$tcx:tt> $($ty:ty,)*) => {
$(impl<'a, $tcx> Decodable<CacheDecoder<'a, $tcx>> for &$tcx [$ty] {
fn decode(d: &mut CacheDecoder<'a, $tcx>) -> Self {
RefDecodable::decode(d)
}
})*
};
}
impl_ref_decoder! {<'tcx>
Span,
rustc_ast::Attribute,
rustc_span::symbol::Ident,
ty::Variance,
rustc_span::def_id::DefId,
rustc_span::def_id::LocalDefId,
(rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo),
}
//- ENCODING -------------------------------------------------------------------
/// An encoder that can write to the incremental compilation cache.
pub struct CacheEncoder<'a, 'tcx> {
2019-06-13 21:48:52 +00:00
tcx: TyCtxt<'tcx>,
encoder: FileEncoder,
2019-04-25 20:54:19 +00:00
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
interpret_allocs: FxIndexSet<interpret::AllocId>,
source_map: CachingSourceMapView<'tcx>,
2018-08-18 10:13:52 +00:00
file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
hygiene_context: &'a HygieneEncodeContext,
symbol_table: FxHashMap<Symbol, usize>,
}
impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
2018-08-18 10:13:56 +00:00
fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
self.file_to_file_index[&(&*source_file as *const SourceFile)]
}
/// Encode something with additional information that allows to do some
/// sanity checks when decoding the data again. This method will first
/// encode the specified tag, then the given value, then the number of
/// bytes taken up by tag and value. On decoding, we can then verify that
/// we get the expected tag and read the expected number of bytes.
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
let start_pos = self.position();
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
tag.encode(self);
value.encode(self);
let end_pos = self.position();
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
((end_pos - start_pos) as u64).encode(self);
}
fn finish(self) -> Result<usize, io::Error> {
self.encoder.finish()
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for SyntaxContext {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s);
2020-03-17 15:45:02 +00:00
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for ExpnId {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
2021-06-27 08:38:06 +00:00
s.hygiene_context.schedule_expn_data_for_encoding(*self);
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
self.expn_hash().encode(s);
2020-03-17 15:45:02 +00:00
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Span {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
2021-04-30 18:15:22 +00:00
let span_data = self.data_untracked();
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
span_data.ctxt.encode(s);
span_data.parent.encode(s);
2021-04-18 12:27:28 +00:00
if span_data.is_dummy() {
return TAG_PARTIAL_SPAN.encode(s);
}
if let Some(parent) = span_data.parent {
let enclosing = s.tcx.source_span(parent).data_untracked();
2021-04-18 12:27:28 +00:00
if enclosing.contains(span_data) {
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
TAG_RELATIVE_SPAN.encode(s);
(span_data.lo - enclosing.lo).to_u32().encode(s);
(span_data.hi - enclosing.lo).to_u32().encode(s);
return;
2021-04-18 12:27:28 +00:00
}
}
let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
let partial_span = match &pos {
Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
None => true,
};
if partial_span {
2021-04-18 12:27:28 +00:00
return TAG_PARTIAL_SPAN.encode(s);
}
let (file_lo, line_lo, col_lo) = pos.unwrap();
let len = span_data.hi - span_data.lo;
let source_file_index = s.source_file_index(file_lo);
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
TAG_FULL_SPAN.encode(s);
source_file_index.encode(s);
line_lo.encode(s);
col_lo.encode(s);
len.encode(s);
}
}
// copy&paste impl from rustc_metadata
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Symbol {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
// if symbol preinterned, emit tag and symbol index
if self.is_preinterned() {
s.encoder.emit_u8(SYMBOL_PREINTERNED);
s.encoder.emit_u32(self.as_u32());
} else {
// otherwise write it as string or as offset to it
match s.symbol_table.entry(*self) {
Entry::Vacant(o) => {
s.encoder.emit_u8(SYMBOL_STR);
let pos = s.encoder.position();
o.insert(pos);
s.emit_str(self.as_str());
}
Entry::Occupied(o) => {
let x = o.get().clone();
s.emit_u8(SYMBOL_OFFSET);
s.emit_usize(x);
}
}
}
}
}
impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
type I = TyCtxt<'tcx>;
const CLEAR_CROSS_CRATE: bool = false;
fn position(&self) -> usize {
self.encoder.position()
}
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
&mut self.type_shorthands
}
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
&mut self.predicate_shorthands
}
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) {
let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
index.encode(self);
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for CrateNum {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
s.tcx.stable_crate_id(*self).encode(s);
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefId {
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
s.tcx.def_path_hash(*self).encode(s);
}
}
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefIndex {
fn encode(&self, _: &mut CacheEncoder<'a, 'tcx>) {
bug!("encoding `DefIndex` without context");
}
}
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
#[inline]
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
$(fn $name(&mut self, value: $ty) {
self.encoder.$name(value)
})*
}
}
impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
encoder_methods! {
emit_usize(usize);
emit_u128(u128);
emit_u64(u64);
emit_u32(u32);
emit_u16(u16);
emit_u8(u8);
emit_isize(isize);
emit_i128(i128);
emit_i64(i64);
emit_i32(i32);
emit_i16(i16);
emit_i8(i8);
emit_bool(bool);
emit_f64(f64);
emit_f32(f32);
emit_char(char);
emit_str(&str);
emit_raw_bytes(&[u8]);
}
}
// This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
// and the encoding traits currently work.
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for [u8] {
fn encode(&self, e: &mut CacheEncoder<'a, 'tcx>) {
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
self.encode(&mut e.encoder);
}
}
pub fn encode_query_results<'a, 'tcx, CTX, Q>(
tcx: CTX,
encoder: &mut CacheEncoder<'a, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex,
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
) where
CTX: QueryContext + 'tcx,
2021-10-17 15:37:20 +00:00
Q: super::QueryDescription<CTX>,
Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
{
let _timer = tcx
.dep_context()
.profiler()
Remove `-Ztime` option. The compiler currently has `-Ztime` and `-Ztime-passes`. I've used `-Ztime-passes` for years but only recently learned about `-Ztime`. What's the difference? Let's look at the `-Zhelp` output: ``` -Z time=val -- measure time of rustc processes (default: no) -Z time-passes=val -- measure time of each rustc pass (default: no) ``` The `-Ztime-passes` description is clear, but the `-Ztime` one is less so. Sounds like it measures the time for the entire process? No. The real difference is that `-Ztime-passes` prints out info about passes, and `-Ztime` does the same, but only for a subset of those passes. More specifically, there is a distinction in the profiling code between a "verbose generic activity" and an "extra verbose generic activity". `-Ztime-passes` prints both kinds, while `-Ztime` only prints the first one. (It took me a close reading of the source code to determine this difference.) In practice this distinction has low value. Perhaps in the past the "extra verbose" output was more voluminous, but now that we only print stats for a pass if it exceeds 5ms or alters the RSS, `-Ztime-passes` is less spammy. Also, a lot of the "extra verbose" cases are for individual lint passes, and you need to also use `-Zno-interleave-lints` to see those anyway. Therefore, this commit removes `-Ztime` and the associated machinery. One thing to note is that the existing "extra verbose" activities all have an extra string argument, so the commit adds the ability to accept an extra argument to the "verbose" activities.
2022-10-06 03:51:45 +00:00
.verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::<Q>());
2018-03-15 09:17:04 +00:00
assert!(Q::query_state(tcx).all_inactive());
let cache = Q::query_cache(tcx);
cache.iter(&mut |key, value, dep_node| {
if Q::cache_on_disk(*tcx.dep_context(), &key) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
// Record position of the cache entry.
query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.encoder.position())));
// Encode the type check tables with the `SerializedDepNodeIndex`
// as tag.
Use delayed error handling for `Encodable` and `Encoder` infallible. There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 03:30:45 +00:00
encoder.encode_tagged(dep_node, value);
}
});
}