2022-07-03 16:18:53 +00:00
|
|
|
use std::collections::hash_map::Entry;
|
2017-10-19 12:32:39 +00:00
|
|
|
use std::mem;
|
2025-02-03 03:44:41 +00:00
|
|
|
use std::sync::Arc;
|
2024-07-28 22:13:50 +00:00
|
|
|
|
2022-10-27 13:23:26 +00:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
2021-03-16 20:39:03 +00:00
|
|
|
use rustc_data_structures::memmap::Mmap;
|
2025-02-03 03:44:41 +00:00
|
|
|
use rustc_data_structures::sync::{HashMapExt, Lock, RwLock};
|
2021-01-02 04:51:07 +00:00
|
|
|
use rustc_data_structures::unhash::UnhashMap;
|
2023-12-21 13:21:01 +00:00
|
|
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
2021-05-30 15:54:49 +00:00
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
|
2021-06-08 20:18:53 +00:00
|
|
|
use rustc_hir::definitions::DefPathHash;
|
2023-04-19 10:57:17 +00:00
|
|
|
use rustc_index::{Idx, IndexVec};
|
2024-04-29 01:14:55 +00:00
|
|
|
use rustc_macros::{Decodable, Encodable};
|
2023-03-25 08:46:19 +00:00
|
|
|
use rustc_query_system::query::QuerySideEffects;
|
2022-06-14 04:52:01 +00:00
|
|
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
|
2020-12-07 01:30:55 +00:00
|
|
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
2021-05-30 15:54:49 +00:00
|
|
|
use rustc_session::Session;
|
2020-03-17 15:45:02 +00:00
|
|
|
use rustc_span::hygiene::{
|
2021-06-24 19:02:09 +00:00
|
|
|
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
|
2020-03-17 15:45:02 +00:00
|
|
|
};
|
2024-11-03 20:50:46 +00:00
|
|
|
use rustc_span::source_map::Spanned;
|
2023-12-19 21:34:26 +00:00
|
|
|
use rustc_span::{
|
2023-12-31 19:35:32 +00:00
|
|
|
BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span,
|
|
|
|
SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
|
2023-12-19 21:34:26 +00:00
|
|
|
};
|
2017-10-19 12:32:39 +00:00
|
|
|
|
2025-02-11 02:58:38 +00:00
|
|
|
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
|
|
|
|
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
|
|
|
|
use crate::mir::mono::MonoItem;
|
|
|
|
use crate::mir::{self, interpret};
|
|
|
|
use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
|
|
|
|
use crate::ty::{self, Ty, TyCtxt};
|
|
|
|
|
2017-11-28 15:58:02 +00:00
|
|
|
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
|
2017-11-14 13:50:03 +00:00
|
|
|
|
2021-01-03 15:09:32 +00:00
|
|
|
// 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;
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2020-03-17 15:45:02 +00:00
|
|
|
const TAG_SYNTAX_CONTEXT: u8 = 0;
|
|
|
|
const TAG_EXPN_DATA: u8 = 1;
|
|
|
|
|
2022-07-03 16:18:53 +00:00
|
|
|
// Tags for encoding Symbol's
|
|
|
|
const SYMBOL_STR: u8 = 0;
|
|
|
|
const SYMBOL_OFFSET: u8 = 1;
|
2022-08-20 12:39:21 +00:00
|
|
|
const SYMBOL_PREINTERNED: u8 = 2;
|
2022-07-03 16:18:53 +00:00
|
|
|
|
2019-09-06 02:57:44 +00:00
|
|
|
/// Provides an interface to incremental compilation data cached from the
|
2017-10-24 12:51:26 +00:00
|
|
|
/// 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
|
2021-07-23 21:40:26 +00:00
|
|
|
/// any side effects that have been emitted during a query.
|
2024-11-03 20:50:46 +00:00
|
|
|
pub struct OnDiskCache {
|
2017-11-14 15:15:45 +00:00
|
|
|
// The complete cache data in serialized form.
|
2021-03-17 21:49:16 +00:00
|
|
|
serialized_data: RwLock<Option<Mmap>>,
|
2017-11-14 15:15:45 +00:00
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
// Collects all `QuerySideEffects` created during the current compilation
|
2019-09-06 02:57:44 +00:00
|
|
|
// session.
|
2021-07-23 21:40:26 +00:00
|
|
|
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
|
2017-10-24 12:51:26 +00:00
|
|
|
|
2021-06-21 13:30:16 +00:00
|
|
|
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2019-09-06 02:57:44 +00:00
|
|
|
// Caches that are populated lazily during decoding.
|
2025-02-03 03:44:41 +00:00
|
|
|
file_index_to_file: Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
|
2017-11-14 15:15:45 +00:00
|
|
|
|
|
|
|
// A map from dep-node to the position of the cached query result in
|
|
|
|
// `serialized_data`.
|
2017-11-28 13:19:44 +00:00
|
|
|
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
2017-11-28 15:58:02 +00:00
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
// A map from dep-node to the position of any associated `QuerySideEffects` in
|
2017-11-28 15:58:02 +00:00
|
|
|
// `serialized_data`.
|
2021-07-23 21:40:26 +00:00
|
|
|
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
2018-03-16 08:59:42 +00:00
|
|
|
|
2018-05-25 15:19:31 +00:00
|
|
|
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`.
|
2021-06-27 13:51:25 +00:00
|
|
|
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
|
2020-03-17 15:45:02 +00:00
|
|
|
// Additional information used when decoding hygiene data.
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: HygieneDecodeContext,
|
2021-07-21 11:38:29 +00:00
|
|
|
// 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.
|
2021-06-27 13:51:25 +00:00
|
|
|
foreign_expn_data: UnhashMap<ExpnHash, u32>,
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 15:45:02 +00:00
|
|
|
// This type is used only for serialization and deserialization.
|
2020-06-11 14:49:57 +00:00
|
|
|
#[derive(Encodable, Decodable)]
|
2017-11-28 15:58:02 +00:00
|
|
|
struct Footer {
|
2021-06-21 13:30:16 +00:00
|
|
|
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
2021-07-23 21:40:26 +00:00
|
|
|
query_result_index: EncodedDepNodeIndex,
|
|
|
|
side_effects_index: EncodedDepNodeIndex,
|
2019-09-06 02:57:44 +00:00
|
|
|
// The location of all allocations.
|
2023-07-11 01:39:28 +00:00
|
|
|
// Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64
|
|
|
|
// without measurable overhead. This permits larger const allocations without ICEing.
|
|
|
|
interpret_alloc_index: Vec<u64>,
|
2020-03-17 15:45:02 +00:00
|
|
|
// See `OnDiskCache.syntax_contexts`
|
|
|
|
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
|
|
|
|
// See `OnDiskCache.expn_data`
|
2021-06-27 13:51:25 +00:00
|
|
|
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
|
|
|
|
foreign_expn_data: UnhashMap<ExpnHash, u32>,
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
|
2017-10-19 12:32:39 +00:00
|
|
|
|
2020-06-11 14:49:57 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
|
2018-08-18 10:13:52 +00:00
|
|
|
struct SourceFileIndex(u32);
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2020-06-11 14:49:57 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
|
2022-11-08 18:47:26 +00:00
|
|
|
pub struct AbsoluteBytePos(u64);
|
2017-11-28 13:19:44 +00:00
|
|
|
|
|
|
|
impl AbsoluteBytePos {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2023-03-25 08:46:19 +00:00
|
|
|
pub fn new(pos: usize) -> AbsoluteBytePos {
|
2022-11-08 18:47:26 +00:00
|
|
|
AbsoluteBytePos(pos.try_into().expect("Incremental cache file size overflowed u64."))
|
2017-11-28 13:19:44 +00:00
|
|
|
}
|
|
|
|
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2017-11-28 13:19:44 +00:00
|
|
|
fn to_usize(self) -> usize {
|
|
|
|
self.0 as usize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-21 13:30:16 +00:00
|
|
|
#[derive(Encodable, Decodable, Clone, Debug)]
|
|
|
|
struct EncodedSourceFileId {
|
2023-12-19 21:34:26 +00:00
|
|
|
stable_source_file_id: StableSourceFileId,
|
2021-06-21 13:30:16 +00:00
|
|
|
stable_crate_id: StableCrateId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EncodedSourceFileId {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2021-06-21 13:30:16 +00:00
|
|
|
fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId {
|
|
|
|
EncodedSourceFileId {
|
2023-12-19 21:34:26 +00:00
|
|
|
stable_source_file_id: file.stable_id,
|
|
|
|
stable_crate_id: tcx.stable_crate_id(file.cnum),
|
2021-06-21 13:30:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-03 20:50:46 +00:00
|
|
|
impl OnDiskCache {
|
2021-03-16 20:39:03 +00:00
|
|
|
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
|
2024-05-22 00:12:07 +00:00
|
|
|
///
|
|
|
|
/// The serialized cache has some basic integrity checks, if those checks indicate that the
|
|
|
|
/// on-disk data is corrupt, an error is returned.
|
2024-11-03 20:50:46 +00:00
|
|
|
pub fn new(sess: &Session, data: Mmap, start_pos: usize) -> Result<Self, ()> {
|
2024-05-04 01:17:57 +00:00
|
|
|
assert!(sess.opts.incremental.is_some());
|
2017-10-19 12:32:39 +00:00
|
|
|
|
2024-05-04 01:17:57 +00:00
|
|
|
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.
|
|
|
|
let footer_pos = decoder
|
|
|
|
.with_position(decoder.len() - IntEncodedWithFixedSize::ENCODED_SIZE, |decoder| {
|
|
|
|
IntEncodedWithFixedSize::decode(decoder).0 as usize
|
|
|
|
});
|
|
|
|
// Decode the file footer, which contains all the lookup tables, etc.
|
|
|
|
let footer: Footer =
|
|
|
|
decoder.with_position(footer_pos, |decoder| decode_tagged(decoder, TAG_FILE_FOOTER));
|
|
|
|
|
2024-05-22 00:12:07 +00:00
|
|
|
Ok(Self {
|
2021-03-17 21:49:16 +00:00
|
|
|
serialized_data: RwLock::new(Some(data)),
|
2017-11-28 15:58:02 +00:00
|
|
|
file_index_to_stable_id: footer.file_index_to_stable_id,
|
2018-10-16 14:57:53 +00:00
|
|
|
file_index_to_file: Default::default(),
|
2021-07-23 21:40:26 +00:00
|
|
|
current_side_effects: Default::default(),
|
2017-11-28 15:58:02 +00:00
|
|
|
query_result_index: footer.query_result_index.into_iter().collect(),
|
2021-07-23 21:40:26 +00:00
|
|
|
prev_side_effects_index: footer.side_effects_index.into_iter().collect(),
|
2018-05-25 15:19:31 +00:00
|
|
|
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,
|
2021-06-27 13:51:25 +00:00
|
|
|
foreign_expn_data: footer.foreign_expn_data,
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: Default::default(),
|
2024-05-04 01:17:57 +00:00
|
|
|
})
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-11-03 20:50:46 +00:00
|
|
|
pub fn new_empty() -> Self {
|
2019-09-06 02:57:44 +00:00
|
|
|
Self {
|
2021-03-17 21:49:16 +00:00
|
|
|
serialized_data: RwLock::new(None),
|
2018-10-16 14:57:53 +00:00
|
|
|
file_index_to_stable_id: Default::default(),
|
|
|
|
file_index_to_file: Default::default(),
|
2021-07-23 21:40:26 +00:00
|
|
|
current_side_effects: Default::default(),
|
2018-10-16 14:57:53 +00:00
|
|
|
query_result_index: Default::default(),
|
2021-07-23 21:40:26 +00:00
|
|
|
prev_side_effects_index: Default::default(),
|
2018-05-25 15:19:31 +00:00
|
|
|
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
|
2020-03-17 15:45:02 +00:00
|
|
|
syntax_contexts: FxHashMap::default(),
|
2021-06-27 13:51:25 +00:00
|
|
|
expn_data: UnhashMap::default(),
|
|
|
|
foreign_expn_data: UnhashMap::default(),
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: Default::default(),
|
2017-10-24 12:51:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
2023-03-25 08:46:19 +00:00
|
|
|
pub fn drop_serialized_data(&self, tcx: TyCtxt<'_>) {
|
2021-03-17 21:49:16 +00:00
|
|
|
// 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);
|
2021-03-17 21:49:16 +00:00
|
|
|
|
|
|
|
*self.serialized_data.write() = None;
|
|
|
|
}
|
|
|
|
|
2023-03-25 08:46:19 +00:00
|
|
|
pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
|
2019-09-06 02:57:44 +00:00
|
|
|
// Serializing the `DepGraph` should not modify it.
|
2017-12-28 05:05:45 +00:00
|
|
|
tcx.dep_graph.with_ignore(|| {
|
2019-09-06 02:57:44 +00:00
|
|
|
// Allocate `SourceFileIndex`es.
|
2017-12-28 05:05:45 +00:00
|
|
|
let (file_to_file_index, file_index_to_stable_id) = {
|
2018-10-19 15:18:03 +00:00
|
|
|
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());
|
2017-12-28 05:05:45 +00:00
|
|
|
|
2018-10-19 15:18:03 +00:00
|
|
|
for (index, file) in files.iter().enumerate() {
|
2018-08-18 10:13:52 +00:00
|
|
|
let index = SourceFileIndex(index as u32);
|
2024-09-27 03:33:26 +00:00
|
|
|
let file_ptr: *const SourceFile = &raw const **file;
|
2017-12-28 05:05:45 +00:00
|
|
|
file_to_file_index.insert(file_ptr, index);
|
2023-11-21 19:07:32 +00:00
|
|
|
let source_file_id = EncodedSourceFileId::new(tcx, file);
|
2021-06-21 13:30:16 +00:00
|
|
|
file_index_to_stable_id.insert(index, source_file_id);
|
2017-12-28 05:05:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
(file_to_file_index, file_index_to_stable_id)
|
|
|
|
};
|
|
|
|
|
2020-07-24 07:01:07 +00:00
|
|
|
let hygiene_encode_context = HygieneEncodeContext::default();
|
|
|
|
|
2017-12-28 05:05:45 +00:00
|
|
|
let mut encoder = CacheEncoder {
|
|
|
|
tcx,
|
|
|
|
encoder,
|
2018-10-16 14:57:53 +00:00
|
|
|
type_shorthands: Default::default(),
|
2021-01-17 07:49:30 +00:00
|
|
|
predicate_shorthands: Default::default(),
|
2018-10-16 14:57:53 +00:00
|
|
|
interpret_allocs: Default::default(),
|
2018-08-18 10:14:25 +00:00
|
|
|
source_map: CachingSourceMapView::new(tcx.sess.source_map()),
|
2017-12-28 05:05:45 +00:00
|
|
|
file_to_file_index,
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: &hygiene_encode_context,
|
2022-07-03 16:18:53 +00:00
|
|
|
symbol_table: Default::default(),
|
2017-12-28 05:05:45 +00:00
|
|
|
};
|
|
|
|
|
2019-09-06 02:57:44 +00:00
|
|
|
// Encode query results.
|
2021-07-23 21:40:26 +00:00
|
|
|
let mut query_result_index = EncodedDepNodeIndex::new();
|
2017-12-28 05:05:45 +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
|
|
|
tcx.sess.time("encode_query_results", || {
|
2017-12-28 05:05:45 +00:00
|
|
|
let enc = &mut encoder;
|
|
|
|
let qri = &mut query_result_index;
|
2023-03-25 08:46:19 +00:00
|
|
|
(tcx.query_system.fns.encode_query_results)(tcx, enc, qri);
|
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
|
|
|
});
|
2018-03-09 06:09:24 +00:00
|
|
|
|
2021-07-23 21:40:26 +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);
|
2020-12-07 01:30:55 +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
|
|
|
(dep_node_index, pos)
|
|
|
|
})
|
|
|
|
.collect();
|
2017-12-28 05:05:45 +00:00
|
|
|
|
2018-04-10 07:58:46 +00:00
|
|
|
let interpret_alloc_index = {
|
|
|
|
let mut interpret_alloc_index = Vec::new();
|
|
|
|
let mut n = 0;
|
|
|
|
loop {
|
2020-08-08 03:44:47 +00:00
|
|
|
let new_n = encoder.interpret_allocs.len();
|
2019-09-06 02:57:44 +00:00
|
|
|
// If we have found new IDs, serialize those too.
|
2018-04-13 16:48:41 +00:00
|
|
|
if n == new_n {
|
2019-09-06 02:57:44 +00:00
|
|
|
// 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);
|
2018-04-10 07:58:46 +00:00
|
|
|
for idx in n..new_n {
|
2020-08-08 03:44:47 +00:00
|
|
|
let id = encoder.interpret_allocs[idx];
|
2023-07-11 01:39:28 +00:00
|
|
|
let pos: u64 = encoder.position().try_into().unwrap();
|
2018-04-10 07:58:46 +00:00
|
|
|
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);
|
2018-04-10 07:58:46 +00:00
|
|
|
}
|
|
|
|
n = new_n;
|
|
|
|
}
|
|
|
|
interpret_alloc_index
|
|
|
|
};
|
|
|
|
|
2020-03-17 15:45:02 +00:00
|
|
|
let mut syntax_contexts = FxHashMap::default();
|
2021-06-27 13:51:25 +00:00
|
|
|
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.
|
|
|
|
|
2020-07-24 07:01:07 +00:00
|
|
|
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| {
|
2020-07-24 07:01:07 +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_SYNTAX_CONTEXT, ctxt_data);
|
2020-07-24 07:01:07 +00:00
|
|
|
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| {
|
2021-06-27 13:51:25 +00:00
|
|
|
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);
|
2021-06-27 13:51:25 +00:00
|
|
|
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
|
|
|
}
|
2020-07-24 07:01:07 +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
|
|
|
|
2023-03-03 03:15:15 +00:00
|
|
|
// Encode the file footer.
|
2017-12-28 05:05:45 +00:00
|
|
|
let footer_pos = encoder.position() as u64;
|
|
|
|
encoder.encode_tagged(
|
|
|
|
TAG_FILE_FOOTER,
|
|
|
|
&Footer {
|
|
|
|
file_index_to_stable_id,
|
|
|
|
query_result_index,
|
2021-07-23 21:40:26 +00:00
|
|
|
side_effects_index,
|
2018-04-10 07:58:46 +00:00
|
|
|
interpret_alloc_index,
|
2020-03-17 15:45:02 +00:00
|
|
|
syntax_contexts,
|
2021-06-27 13:51:25 +00:00
|
|
|
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
|
|
|
},
|
|
|
|
);
|
2017-12-28 05:05: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);
|
2017-12-28 05:05:45 +00:00
|
|
|
|
|
|
|
// 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()
|
2017-12-28 05:05:45 +00:00
|
|
|
})
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
2021-06-28 19:12:01 +00:00
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
/// Loads a `QuerySideEffects` created during the previous compilation session.
|
|
|
|
pub fn load_side_effects(
|
2019-06-11 21:11:55 +00:00
|
|
|
&self,
|
2019-06-21 21:49:03 +00:00
|
|
|
tcx: TyCtxt<'_>,
|
2019-06-11 21:11:55 +00:00
|
|
|
dep_node_index: SerializedDepNodeIndex,
|
2021-07-23 21:40:26 +00:00
|
|
|
) -> QuerySideEffects {
|
|
|
|
let side_effects: Option<QuerySideEffects> =
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
|
2017-11-28 15:58:02 +00:00
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
side_effects.unwrap_or_default()
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
/// Stores a `QuerySideEffects` emitted during the current compilation session.
|
|
|
|
/// Anything stored like this will be available via `load_side_effects` in
|
2017-10-24 12:51:26 +00:00
|
|
|
/// the next compilation session.
|
2021-07-23 21:40:26 +00:00
|
|
|
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);
|
2017-10-19 12:32:39 +00:00
|
|
|
debug_assert!(prev.is_none());
|
|
|
|
}
|
|
|
|
|
2023-03-06 14:57:05 +00:00
|
|
|
/// Return whether the cached query result can be decoded.
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2023-03-06 14:57:05 +00:00
|
|
|
pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool {
|
|
|
|
self.query_result_index.contains_key(&dep_node_index)
|
|
|
|
// with_decoder is infallible, so we can stop here
|
|
|
|
}
|
|
|
|
|
2017-11-28 16:32:28 +00:00
|
|
|
/// 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`.
|
2021-01-19 19:40:16 +00:00
|
|
|
pub fn try_load_query_result<'tcx, T>(
|
2019-06-11 21:11:55 +00:00
|
|
|
&self,
|
2020-06-11 14:49:57 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-06-11 21:11:55 +00:00
|
|
|
dep_node_index: SerializedDepNodeIndex,
|
|
|
|
) -> Option<T>
|
|
|
|
where
|
2020-06-11 14:49:57 +00:00
|
|
|
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
|
2017-11-14 15:15:45 +00:00
|
|
|
{
|
2023-03-06 14:57:05 +00:00
|
|
|
let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index);
|
|
|
|
debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index));
|
|
|
|
opt_value
|
2017-11-28 15:58:02 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
/// Stores side effect emitted during computation of an anonymous query.
|
2017-11-28 15:58:02 +00:00
|
|
|
/// 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`.
|
2021-07-23 21:40:26 +00:00
|
|
|
pub fn store_side_effects_for_anon_node(
|
2017-11-28 15:58:02 +00:00
|
|
|
&self,
|
|
|
|
dep_node_index: DepNodeIndex,
|
2021-07-23 21:40:26 +00:00
|
|
|
side_effects: QuerySideEffects,
|
2018-12-07 02:04:23 +00:00
|
|
|
) {
|
2021-07-23 21:40:26 +00:00
|
|
|
let mut current_side_effects = self.current_side_effects.borrow_mut();
|
2017-11-28 15:58:02 +00:00
|
|
|
|
2021-07-23 21:40:26 +00:00
|
|
|
let x = current_side_effects.entry(dep_node_index).or_default();
|
|
|
|
x.append(side_effects);
|
2017-11-28 15:58:02 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 21:11:55 +00:00
|
|
|
fn load_indexed<'tcx, T>(
|
|
|
|
&self,
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-06-11 21:11:55 +00:00
|
|
|
dep_node_index: SerializedDepNodeIndex,
|
|
|
|
index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
|
|
|
) -> Option<T>
|
|
|
|
where
|
2020-06-11 14:49:57 +00:00
|
|
|
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
|
2017-11-28 15:58:02 +00:00
|
|
|
{
|
2018-12-19 12:19:48 +00:00
|
|
|
let pos = index.get(&dep_node_index).cloned()?;
|
2023-03-06 14:57:05 +00:00
|
|
|
let value = self.with_decoder(tcx, pos, |decoder| decode_tagged(decoder, dep_node_index));
|
|
|
|
Some(value)
|
2020-03-17 15:45:02 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 21:49:16 +00:00
|
|
|
fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(
|
2024-11-03 20:50:46 +00:00
|
|
|
&self,
|
2020-03-17 15:45:02 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
pos: AbsoluteBytePos,
|
|
|
|
f: F,
|
|
|
|
) -> T
|
|
|
|
where
|
2020-06-11 14:49:57 +00:00
|
|
|
T: Decodable<CacheDecoder<'a, 'tcx>>,
|
2020-03-17 15:45:02 +00:00
|
|
|
{
|
2021-03-17 21:49:16 +00:00
|
|
|
let serialized_data = self.serialized_data.read();
|
2017-11-14 15:15:45 +00:00
|
|
|
let mut decoder = CacheDecoder {
|
2017-11-28 15:58:02 +00:00
|
|
|
tcx,
|
2024-05-04 01:17:57 +00:00
|
|
|
opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize())
|
|
|
|
.unwrap(),
|
2018-02-13 14:50:37 +00:00
|
|
|
file_index_to_file: &self.file_index_to_file,
|
2017-11-24 13:00:33 +00:00
|
|
|
file_index_to_stable_id: &self.file_index_to_stable_id,
|
2018-05-25 15:19:31 +00:00
|
|
|
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,
|
2021-06-27 13:51:25 +00:00
|
|
|
foreign_expn_data: &self.foreign_expn_data,
|
2020-03-17 15:45:02 +00:00
|
|
|
hygiene_context: &self.hygiene_context,
|
2017-11-14 15:15:45 +00:00
|
|
|
};
|
2020-03-17 15:45:02 +00:00
|
|
|
f(&mut decoder)
|
2017-11-14 15:15:45 +00:00
|
|
|
}
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 15:35:51 +00:00
|
|
|
//- DECODING -------------------------------------------------------------------
|
|
|
|
|
2020-12-19 22:25:24 +00:00
|
|
|
/// A decoder that can read from the incremental compilation cache. It is similar to the one
|
2019-09-06 02:57:44 +00:00
|
|
|
/// we use for crate metadata decoding in that it can rebase spans and eventually
|
|
|
|
/// will also handle things that contain `Ty` instances.
|
2021-01-19 19:40:16 +00:00
|
|
|
pub struct CacheDecoder<'a, 'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-06-14 04:52:01 +00:00
|
|
|
opaque: MemDecoder<'a>,
|
2025-02-03 03:44:41 +00:00
|
|
|
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
|
2021-06-21 13:30:16 +00:00
|
|
|
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
2019-06-11 19:03:44 +00:00
|
|
|
alloc_decoding_session: AllocDecodingSession<'a>,
|
2020-03-17 15:45:02 +00:00
|
|
|
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
|
2021-06-27 13:51:25 +00:00
|
|
|
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
|
|
|
|
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: &'a HygieneDecodeContext,
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 19:03:44 +00:00
|
|
|
impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2025-02-03 03:44:41 +00:00
|
|
|
fn file_index_to_file(&self, index: SourceFileIndex) -> Arc<SourceFile> {
|
2024-11-03 20:50:46 +00:00
|
|
|
let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, .. } = *self;
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2025-02-03 03:44:41 +00:00
|
|
|
Arc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
|
2024-10-07 19:22:51 +00:00
|
|
|
let source_file_id = &file_index_to_stable_id[&index];
|
|
|
|
let source_file_cnum = tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id);
|
|
|
|
|
|
|
|
// 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 source_file_cnum != LOCAL_CRATE {
|
|
|
|
self.tcx.import_source_files(source_file_cnum);
|
|
|
|
}
|
|
|
|
|
2024-11-03 20:50:46 +00:00
|
|
|
tcx.sess
|
|
|
|
.source_map()
|
2024-10-07 19:22:51 +00:00
|
|
|
.source_file_by_stable_id(source_file_id.stable_source_file_id)
|
|
|
|
.expect("failed to lookup `SourceFile` in new context")
|
|
|
|
}))
|
2017-10-19 12:32:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-06 02:57:44 +00:00
|
|
|
// Decodes something that was encoded with `encode_tagged()` and verify that the
|
2017-11-14 13:50:03 +00:00
|
|
|
// tag matches and the correct amount of bytes was read.
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> V
|
2019-06-16 09:41:24 +00:00
|
|
|
where
|
2020-10-13 08:17:05 +00:00
|
|
|
T: Decodable<D> + Eq + std::fmt::Debug,
|
2020-06-11 14:49:57 +00:00
|
|
|
V: Decodable<D>,
|
2023-04-21 03:11:47 +00:00
|
|
|
D: Decoder,
|
2017-11-14 13:50:03 +00:00
|
|
|
{
|
|
|
|
let start_pos = decoder.position();
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
let actual_tag = T::decode(decoder);
|
2017-11-14 13:50:03 +00:00
|
|
|
assert_eq!(actual_tag, expected_tag);
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
let value = V::decode(decoder);
|
2017-11-14 13:50:03 +00:00
|
|
|
let end_pos = decoder.position();
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
let expected_len: u64 = Decodable::decode(decoder);
|
2017-11-14 13:50:03 +00:00
|
|
|
assert_eq!((end_pos - start_pos) as u64, expected_len);
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
value
|
2017-11-14 13:50:03 +00:00
|
|
|
}
|
|
|
|
|
2025-03-13 17:53:36 +00:00
|
|
|
impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
|
2020-06-11 14:49:57 +00:00
|
|
|
const CLEAR_CROSS_CRATE: bool = false;
|
|
|
|
|
2017-11-14 11:03:57 +00:00
|
|
|
#[inline]
|
2022-05-28 03:03:57 +00:00
|
|
|
fn interner(&self) -> TyCtxt<'tcx> {
|
|
|
|
self.tcx
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
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
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
F: FnOnce(&mut Self) -> Ty<'tcx>,
|
2017-11-14 11:03:57 +00:00
|
|
|
{
|
2021-01-31 09:32:34 +00:00
|
|
|
let tcx = self.tcx;
|
2017-11-14 11:03:57 +00:00
|
|
|
|
2021-05-30 12:06:26 +00:00
|
|
|
let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand };
|
2017-11-14 11:03:57 +00:00
|
|
|
|
2020-06-10 08:26:54 +00:00
|
|
|
if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
return ty;
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
let ty = or_insert_with(self);
|
2019-09-06 02:57:44 +00:00
|
|
|
// 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);
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
ty
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut Self) -> R,
|
|
|
|
{
|
2023-04-21 03:11:47 +00:00
|
|
|
debug_assert!(pos < self.opaque.len());
|
2017-11-14 11:03:57 +00:00
|
|
|
|
2024-05-04 01:17:57 +00:00
|
|
|
let new_opaque = self.opaque.split_at(pos);
|
2017-11-14 11:03:57 +00:00
|
|
|
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
|
|
|
|
let r = f(self);
|
|
|
|
self.opaque = old_opaque;
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode_alloc_id(&mut self) -> interpret::AllocId {
|
2020-06-11 14:49:57 +00:00
|
|
|
let alloc_decoding_session = self.alloc_decoding_session;
|
|
|
|
alloc_decoding_session.decode_alloc_id(self)
|
|
|
|
}
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
2025-02-11 02:58:38 +00:00
|
|
|
crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
|
2017-11-16 14:26:00 +00:00
|
|
|
|
2020-12-17 05:03:45 +00:00
|
|
|
// 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> {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
2020-12-17 05:03:45 +00:00
|
|
|
Decodable::decode(&mut d.opaque)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
|
|
|
|
fn decode_syntax_context(&mut self) -> SyntaxContext {
|
|
|
|
let syntax_contexts = self.syntax_contexts;
|
|
|
|
rustc_span::hygiene::decode_syntax_context(self, self.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| {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
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
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
fn decode_expn_id(&mut self) -> ExpnId {
|
|
|
|
let hash = ExpnHash::decode(self);
|
2021-06-27 13:51:25 +00:00
|
|
|
if hash.is_root() {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
return ExpnId::root();
|
2021-06-27 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(expn_id) = ExpnId::from_hash(hash) {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
return expn_id;
|
2021-06-27 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
let krate = self.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
|
2021-06-27 13:51:25 +00:00
|
|
|
|
|
|
|
let expn_id = if krate == LOCAL_CRATE {
|
|
|
|
// We look up the position of the associated `ExpnData` and decode it.
|
2023-12-31 20:27:35 +00:00
|
|
|
let pos = self
|
2021-06-27 13:51:25 +00:00
|
|
|
.expn_data
|
|
|
|
.get(&hash)
|
2023-12-31 20:27:35 +00:00
|
|
|
.unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, self.expn_data));
|
2021-06-27 13:51:25 +00:00
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
let data: ExpnData =
|
|
|
|
self.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};
|
2023-12-31 20:27:35 +00:00
|
|
|
let local_hash = self.tcx.with_stable_hashing_context(|mut hcx| {
|
2021-07-12 20:19:25 +00:00
|
|
|
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
|
2021-06-27 13:51:25 +00:00
|
|
|
} else {
|
2023-12-31 20:27:35 +00:00
|
|
|
let index_guess = self.foreign_expn_data[&hash];
|
2024-03-26 12:31:41 +00:00
|
|
|
self.tcx.expn_hash_to_expn_id(krate, index_guess, hash)
|
2021-06-27 13:51:25 +00:00
|
|
|
};
|
|
|
|
|
2021-10-02 19:14:52 +00:00
|
|
|
debug_assert_eq!(expn_id.krate, krate);
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
expn_id
|
2020-03-17 15:45:02 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
fn decode_span(&mut self) -> Span {
|
|
|
|
let ctxt = SyntaxContext::decode(self);
|
|
|
|
let parent = Option::<LocalDefId>::decode(self);
|
|
|
|
let tag: u8 = Decodable::decode(self);
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2021-01-03 15:09:32 +00:00
|
|
|
if tag == TAG_PARTIAL_SPAN {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
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 {
|
2023-12-31 19:35:32 +00:00
|
|
|
let dlo = u32::decode(self);
|
|
|
|
let dto = u32::decode(self);
|
2021-04-18 12:27:28 +00:00
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
let enclosing = self.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,
|
|
|
|
);
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
return span;
|
2017-11-24 13:00:33 +00:00
|
|
|
} else {
|
2021-01-03 15:09:32 +00:00
|
|
|
debug_assert_eq!(tag, TAG_FULL_SPAN);
|
2017-10-24 12:51:26 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
let file_lo_index = SourceFileIndex::decode(self);
|
|
|
|
let line_lo = usize::decode(self);
|
|
|
|
let col_lo = RelativeBytePos::decode(self);
|
|
|
|
let len = BytePos::decode(self);
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
let file_lo = self.file_index_to_file(file_lo_index);
|
2023-08-31 20:12:47 +00:00
|
|
|
let lo = file_lo.lines()[line_lo - 1] + col_lo;
|
2023-09-03 10:15:35 +00:00
|
|
|
let lo = file_lo.absolute_position(lo);
|
2017-11-24 13:00:33 +00:00
|
|
|
let hi = lo + len;
|
|
|
|
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
Span::new(lo, hi, ctxt, parent)
|
2017-10-24 12:51:26 +00:00
|
|
|
}
|
2017-11-13 15:35:51 +00:00
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
// copy&paste impl from rustc_metadata
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2023-12-31 20:27:35 +00:00
|
|
|
fn decode_symbol(&mut self) -> Symbol {
|
|
|
|
let tag = self.read_u8();
|
2022-07-03 16:18:53 +00:00
|
|
|
|
|
|
|
match tag {
|
|
|
|
SYMBOL_STR => {
|
2023-12-31 20:27:35 +00:00
|
|
|
let s = self.read_str();
|
2022-07-03 16:18:53 +00:00
|
|
|
Symbol::intern(s)
|
|
|
|
}
|
|
|
|
SYMBOL_OFFSET => {
|
|
|
|
// read str offset
|
2023-12-31 20:27:35 +00:00
|
|
|
let pos = self.read_usize();
|
2022-07-03 16:18:53 +00:00
|
|
|
|
2023-04-09 21:35:02 +00:00
|
|
|
// move to str offset and read
|
2023-12-31 20:27:35 +00:00
|
|
|
self.opaque.with_position(pos, |d| {
|
2023-04-21 03:11:47 +00:00
|
|
|
let s = d.read_str();
|
|
|
|
Symbol::intern(s)
|
|
|
|
})
|
2022-07-03 16:18:53 +00:00
|
|
|
}
|
2022-08-20 12:39:21 +00:00
|
|
|
SYMBOL_PREINTERNED => {
|
2023-12-31 20:27:35 +00:00
|
|
|
let symbol_index = self.read_u32();
|
2022-08-20 12:39:21 +00:00
|
|
|
Symbol::new_from_decoded(symbol_index)
|
|
|
|
}
|
2022-07-03 16:18:53 +00:00
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
fn decode_crate_num(&mut self) -> CrateNum {
|
|
|
|
let stable_id = StableCrateId::decode(self);
|
|
|
|
let cnum = self.tcx.stable_crate_id_to_crate_num(stable_id);
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
cnum
|
2019-08-24 15:25:55 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
// 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.
|
|
|
|
fn decode_def_index(&mut self) -> DefIndex {
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
panic!("trying to decode `DefIndex` outside the context of a `DefId`")
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
|
|
|
|
// compilation sessions. We use the `DefPathHash`, which is stable across
|
|
|
|
// sessions, to map the old `DefId` to the new one.
|
|
|
|
fn decode_def_id(&mut self) -> DefId {
|
2019-09-06 02:57:44 +00:00
|
|
|
// Load the `DefPathHash` which is was we encoded the `DefId` as.
|
2023-12-31 20:27:35 +00:00
|
|
|
let def_path_hash = DefPathHash::decode(self);
|
2017-11-14 11:03:57 +00:00
|
|
|
|
2019-09-06 02:57:44 +00:00
|
|
|
// Using the `DefPathHash`, we can lookup the new `DefId`.
|
2020-07-29 16:26:15 +00:00
|
|
|
// 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.
|
2024-06-13 12:46:30 +00:00
|
|
|
match self.tcx.def_path_hash_to_def_id(def_path_hash) {
|
|
|
|
Some(r) => r,
|
|
|
|
None => panic!("Failed to convert DefPathHash {def_path_hash:?}"),
|
|
|
|
}
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
2023-12-31 20:40:09 +00:00
|
|
|
|
|
|
|
fn decode_attr_id(&mut self) -> rustc_span::AttrId {
|
|
|
|
panic!("cannot decode `AttrId` with `CacheDecoder`");
|
|
|
|
}
|
2017-11-14 11:03:57 +00:00
|
|
|
}
|
|
|
|
|
2022-10-27 13:23:26 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId> {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
2020-06-11 14:49:57 +00:00
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-17 17:46:01 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
|
2024-05-27 00:03:47 +00:00
|
|
|
for &'tcx UnordMap<DefId, ty::EarlyBinder<'tcx, Ty<'tcx>>>
|
2023-04-17 17:46:01 +00:00
|
|
|
{
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2022-09-09 15:34:11 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-11 14:49:57 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
|
|
|
|
for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
|
|
|
|
{
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
2020-06-11 14:49:57 +00:00
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-19 20:46:46 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
|
|
|
|
#[inline]
|
|
|
|
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] {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
Make `Decodable` and `Decoder` infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
2022-01-18 02:22:50 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
2020-06-11 14:49:57 +00:00
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-31 03:10:37 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Spanned<MonoItem<'tcx>>] {
|
|
|
|
#[inline]
|
|
|
|
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-11 10:05:12 +00:00
|
|
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
|
|
|
|
for &'tcx crate::traits::specialization_graph::Graph
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
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] {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2022-03-28 17:53:01 +00:00
|
|
|
fn decode(d: &mut CacheDecoder<'a, $tcx>) -> Self {
|
|
|
|
RefDecodable::decode(d)
|
|
|
|
}
|
|
|
|
})*
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_ref_decoder! {<'tcx>
|
|
|
|
Span,
|
2024-10-16 23:14:01 +00:00
|
|
|
rustc_hir::Attribute,
|
2024-12-12 23:29:23 +00:00
|
|
|
rustc_span::Ident,
|
2022-03-28 17:53:01 +00:00
|
|
|
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),
|
Introduce deduced parameter attributes, and use them for deducing `readonly` on
indirect immutable freeze by-value function parameters.
Right now, `rustc` only examines function signatures and the platform ABI when
determining the LLVM attributes to apply to parameters. This results in missed
optimizations, because there are some attributes that can be determined via
analysis of the MIR making up the function body. In particular, `readonly`
could be applied to most indirectly-passed by-value function arguments
(specifically, those that are freeze and are observed not to be mutated), but
it currently is not.
This patch introduces the machinery that allows `rustc` to determine those
attributes. It consists of a query, `deduced_param_attrs`, that, when
evaluated, analyzes the MIR of the function to determine supplementary
attributes. The results of this query for each function are written into the
crate metadata so that the deduced parameter attributes can be applied to
cross-crate functions. In this patch, we simply check the parameter for
mutations to determine whether the `readonly` attribute should be applied to
parameters that are indirect immutable freeze by-value. More attributes could
conceivably be deduced in the future: `nocapture` and `noalias` come to mind.
Adding `readonly` to indirect function parameters where applicable enables some
potential optimizations in LLVM that are discussed in [issue 103103] and [PR
103070] around avoiding stack-to-stack memory copies that appear in functions
like `core::fmt::Write::write_fmt` and `core::panicking::assert_failed`. These
functions pass a large structure unchanged by value to a subfunction that also
doesn't mutate it. Since the structure in this case is passed as an indirect
parameter, it's a pointer from LLVM's perspective. As a result, the
intermediate copy of the structure that our codegen emits could be optimized
away by LLVM's MemCpyOptimizer if it knew that the pointer is `readonly
nocapture noalias` in both the caller and callee. We already pass `nocapture
noalias`, but we're missing `readonly`, as we can't determine whether a
by-value parameter is mutated by examining the signature in Rust. I didn't have
much success with having LLVM infer the `readonly` attribute, even with fat
LTO; it seems that deducing it at the MIR level is necessary.
No large benefits should be expected from this optimization *now*; LLVM needs
some changes (discussed in [PR 103070]) to more aggressively use the `noalias
nocapture readonly` combination in its alias analysis. I have some LLVM patches
for these optimizations and have had them looked over. With all the patches
applied locally, I enabled LLVM to remove all the `memcpy`s from the following
code:
```rust
fn main() {
println!("Hello {}", 3);
}
```
which is a significant codegen improvement over the status quo. I expect that
if this optimization kicks in in multiple places even for such a simple
program, then it will apply to Rust code all over the place.
[issue 103103]: https://github.com/rust-lang/rust/issues/103103
[PR 103070]: https://github.com/rust-lang/rust/pull/103070
2022-10-18 02:42:15 +00:00
|
|
|
ty::DeducedParamAttrs,
|
2017-12-23 03:41:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 15:35:51 +00:00
|
|
|
//- ENCODING -------------------------------------------------------------------
|
|
|
|
|
2020-12-19 22:25:24 +00:00
|
|
|
/// An encoder that can write to the incremental compilation cache.
|
2022-06-16 06:00:25 +00:00
|
|
|
pub struct CacheEncoder<'a, 'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-06-16 06:00:25 +00:00
|
|
|
encoder: FileEncoder,
|
2019-04-25 20:54:19 +00:00
|
|
|
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
2021-01-17 07:49:30 +00:00
|
|
|
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
|
2020-08-08 03:44:47 +00:00
|
|
|
interpret_allocs: FxIndexSet<interpret::AllocId>,
|
2018-08-18 10:14:25 +00:00
|
|
|
source_map: CachingSourceMapView<'tcx>,
|
2018-08-18 10:13:52 +00:00
|
|
|
file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
|
2020-07-24 07:01:07 +00:00
|
|
|
hygiene_context: &'a HygieneEncodeContext,
|
2022-07-03 16:18:53 +00:00
|
|
|
symbol_table: FxHashMap<Symbol, usize>,
|
2017-11-13 15:35:51 +00:00
|
|
|
}
|
|
|
|
|
2022-06-16 06:00:25 +00:00
|
|
|
impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2025-02-03 03:44:41 +00:00
|
|
|
fn source_file_index(&mut self, source_file: Arc<SourceFile>) -> SourceFileIndex {
|
2024-09-27 03:33:26 +00:00
|
|
|
self.file_to_file_index[&(&raw const *source_file)]
|
2017-11-24 13:00:33 +00:00
|
|
|
}
|
|
|
|
|
2017-11-14 13:50:03 +00:00
|
|
|
/// 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.
|
2023-03-25 08:46:19 +00:00
|
|
|
pub fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
|
2017-11-14 13:50:03 +00:00
|
|
|
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);
|
2017-11-14 13:50:03 +00:00
|
|
|
|
|
|
|
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);
|
2017-11-14 13:50:03 +00:00
|
|
|
}
|
2022-06-16 06:00:25 +00:00
|
|
|
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2023-10-28 01:26:43 +00:00
|
|
|
fn finish(mut self) -> FileEncodeResult {
|
2022-06-16 06:00:25 +00:00
|
|
|
self.encoder.finish()
|
|
|
|
}
|
2017-11-14 13:50:03 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
|
|
|
|
fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) {
|
|
|
|
rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_context, self);
|
2020-03-17 15:45:02 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
fn encode_expn_id(&mut self, expn_id: ExpnId) {
|
|
|
|
self.hygiene_context.schedule_expn_data_for_encoding(expn_id);
|
|
|
|
expn_id.expn_hash().encode(self);
|
2020-03-17 15:45:02 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
fn encode_span(&mut self, span: Span) {
|
|
|
|
let span_data = span.data_untracked();
|
|
|
|
span_data.ctxt.encode(self);
|
|
|
|
span_data.parent.encode(self);
|
2021-04-18 12:27:28 +00:00
|
|
|
|
|
|
|
if span_data.is_dummy() {
|
2023-12-31 19:35:32 +00:00
|
|
|
return TAG_PARTIAL_SPAN.encode(self);
|
2021-04-18 12:27:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(parent) = span_data.parent {
|
2023-12-31 19:35:32 +00:00
|
|
|
let enclosing = self.tcx.source_span_untracked(parent).data_untracked();
|
2021-04-18 12:27:28 +00:00
|
|
|
if enclosing.contains(span_data) {
|
2023-12-31 19:35:32 +00:00
|
|
|
TAG_RELATIVE_SPAN.encode(self);
|
|
|
|
(span_data.lo - enclosing.lo).to_u32().encode(self);
|
|
|
|
(span_data.hi - enclosing.lo).to_u32().encode(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
|
|
|
return;
|
2021-04-18 12:27:28 +00:00
|
|
|
}
|
2017-11-24 13:00:33 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
let pos = self.source_map.byte_pos_to_line_and_col(span_data.lo);
|
2021-01-03 15:09:32 +00:00
|
|
|
let partial_span = match &pos {
|
|
|
|
Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
|
|
|
|
None => true,
|
2020-06-11 14:49:57 +00:00
|
|
|
};
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2021-01-03 15:09:32 +00:00
|
|
|
if partial_span {
|
2023-12-31 19:35:32 +00:00
|
|
|
return TAG_PARTIAL_SPAN.encode(self);
|
2017-11-24 13:00:33 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 15:09:32 +00:00
|
|
|
let (file_lo, line_lo, col_lo) = pos.unwrap();
|
|
|
|
|
2017-11-24 13:00:33 +00:00
|
|
|
let len = span_data.hi - span_data.lo;
|
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
let source_file_index = self.source_file_index(file_lo);
|
2017-11-24 13:00:33 +00:00
|
|
|
|
2023-12-31 19:35:32 +00:00
|
|
|
TAG_FULL_SPAN.encode(self);
|
|
|
|
source_file_index.encode(self);
|
|
|
|
line_lo.encode(self);
|
|
|
|
col_lo.encode(self);
|
|
|
|
len.encode(self);
|
2017-11-22 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:27:35 +00:00
|
|
|
// copy&paste impl from rustc_metadata
|
|
|
|
fn encode_symbol(&mut self, symbol: Symbol) {
|
2022-08-20 12:39:21 +00:00
|
|
|
// if symbol preinterned, emit tag and symbol index
|
2023-12-31 20:27:35 +00:00
|
|
|
if symbol.is_preinterned() {
|
|
|
|
self.encoder.emit_u8(SYMBOL_PREINTERNED);
|
|
|
|
self.encoder.emit_u32(symbol.as_u32());
|
2022-08-20 12:39:21 +00:00
|
|
|
} else {
|
|
|
|
// otherwise write it as string or as offset to it
|
2023-12-31 20:27:35 +00:00
|
|
|
match self.symbol_table.entry(symbol) {
|
2022-08-20 12:39:21 +00:00
|
|
|
Entry::Vacant(o) => {
|
2023-12-31 20:27:35 +00:00
|
|
|
self.encoder.emit_u8(SYMBOL_STR);
|
|
|
|
let pos = self.encoder.position();
|
2022-08-20 12:39:21 +00:00
|
|
|
o.insert(pos);
|
2023-12-31 20:27:35 +00:00
|
|
|
self.emit_str(symbol.as_str());
|
2022-08-20 12:39:21 +00:00
|
|
|
}
|
|
|
|
Entry::Occupied(o) => {
|
2022-12-18 13:25:55 +00:00
|
|
|
let x = *o.get();
|
2023-12-31 20:27:35 +00:00
|
|
|
self.emit_u8(SYMBOL_OFFSET);
|
|
|
|
self.emit_usize(x);
|
2022-08-20 12:39:21 +00:00
|
|
|
}
|
2022-07-03 16:18:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-12-31 20:27:35 +00:00
|
|
|
|
|
|
|
fn encode_crate_num(&mut self, crate_num: CrateNum) {
|
|
|
|
self.tcx.stable_crate_id(crate_num).encode(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn encode_def_id(&mut self, def_id: DefId) {
|
|
|
|
self.tcx.def_path_hash(def_id).encode(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn encode_def_index(&mut self, _def_index: DefIndex) {
|
|
|
|
bug!("encoding `DefIndex` without context");
|
|
|
|
}
|
2022-07-03 16:18:53 +00:00
|
|
|
}
|
|
|
|
|
2025-03-13 17:53:36 +00:00
|
|
|
impl<'a, 'tcx> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx> {
|
2020-06-11 14:49:57 +00:00
|
|
|
const CLEAR_CROSS_CRATE: bool = false;
|
2019-08-24 15:25:55 +00:00
|
|
|
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2017-11-13 15:35:51 +00:00
|
|
|
fn position(&self) -> usize {
|
2020-12-07 01:30:55 +00:00
|
|
|
self.encoder.position()
|
2017-11-13 15:35:51 +00:00
|
|
|
}
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2020-06-11 14:49:57 +00:00
|
|
|
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
|
|
|
|
&mut self.type_shorthands
|
2017-11-16 16:13:39 +00:00
|
|
|
}
|
2023-03-28 03:01:24 +00:00
|
|
|
#[inline]
|
2021-01-17 07:49:30 +00:00
|
|
|
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
|
|
|
|
&mut self.predicate_shorthands
|
|
|
|
}
|
2023-03-28 03:01:24 +00:00
|
|
|
#[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 encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) {
|
2020-06-11 14:49:57 +00:00
|
|
|
let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
|
2017-11-13 15:35:51 +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
|
|
|
index.encode(self);
|
2017-11-16 13:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-13 15:35:51 +00:00
|
|
|
macro_rules! encoder_methods {
|
|
|
|
($($name:ident($ty:ty);)*) => {
|
2020-02-19 05:54:36 +00:00
|
|
|
#[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) {
|
2017-11-13 15:35:51 +00:00
|
|
|
self.encoder.$name(value)
|
|
|
|
})*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-16 06:00:25 +00:00
|
|
|
impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
|
2017-11-13 15:35:51 +00:00
|
|
|
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);
|
|
|
|
|
2021-03-11 21:06:45 +00:00
|
|
|
emit_raw_bytes(&[u8]);
|
2017-11-13 15:35:51 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-14 13:50:03 +00:00
|
|
|
|
2020-12-07 01:30:55 +00:00
|
|
|
// 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`.
|
2020-12-17 03:03:31 +00:00
|
|
|
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
|
|
|
|
// and the encoding traits currently work.
|
2022-06-16 06:00:25 +00:00
|
|
|
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);
|
2020-12-17 03:03:31 +00:00
|
|
|
}
|
|
|
|
}
|