rust/compiler/rustc_query_impl/src/lib.rs

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

232 lines
6.5 KiB
Rust
Raw Normal View History

//! Support for serializing the dep-graph and reloading it.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
#![feature(const_mut_refs)]
2023-02-07 01:32:30 -06:00
#![feature(const_refs_to_cell)]
#![feature(min_specialization)]
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-06 22:30:45 -05:00
#![feature(never_type)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
2023-02-07 01:32:30 -06:00
#![allow(rustc::potential_query_instability, unused_parens)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
2023-08-22 06:06:38 -05:00
#![allow(internal_features)]
#[macro_use]
extern crate rustc_middle;
2023-05-17 20:39:35 -05:00
use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
2023-02-07 01:32:30 -06:00
use field_offset::offset_of;
use rustc_data_structures::stable_hasher::HashStable;
use rustc_data_structures::sync::AtomicU64;
2021-10-16 14:12:34 -05:00
use rustc_middle::arena::Arena;
2023-02-07 01:32:30 -06:00
use rustc_middle::dep_graph::DepNodeIndex;
2023-02-07 01:32:30 -06:00
use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
use rustc_middle::query::erase::{erase, restore, Erase};
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
use rustc_middle::query::plumbing::{
DynamicQuery, QueryKeyStringCache, QuerySystem, QuerySystemFns,
};
2023-03-13 17:11:07 -05:00
use rustc_middle::query::AsLocalKey;
use rustc_middle::query::{
2023-05-17 20:39:35 -05:00
queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
};
use rustc_middle::ty::TyCtxt;
2023-02-07 01:32:30 -06:00
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
2023-02-07 01:32:30 -06:00
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
get_query_incr, get_query_non_incr, HashResult, QueryCache, QueryConfig, QueryInfo, QueryMap,
QueryMode, QueryState,
2023-02-07 01:32:30 -06:00
};
use rustc_query_system::HandleCycleError;
2023-02-07 01:32:30 -06:00
use rustc_query_system::Value;
2023-08-27 16:32:55 -05:00
use rustc_span::{ErrorGuaranteed, Span};
#[macro_use]
mod plumbing;
2023-03-25 03:46:19 -05:00
pub use crate::plumbing::QueryCtxt;
mod profiling_support;
pub use self::profiling_support::alloc_self_profile_query_strings;
2023-02-07 01:32:30 -06:00
struct DynamicConfig<
'tcx,
C: QueryCache,
const ANON: bool,
const DEPTH_LIMIT: bool,
const FEEDABLE: bool,
> {
dynamic: &'tcx DynamicQuery<'tcx, C>,
}
2023-02-07 01:32:30 -06:00
2023-02-07 01:32:30 -06:00
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
{
}
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
{
fn clone(&self) -> Self {
DynamicConfig { dynamic: self.dynamic }
}
2023-02-07 01:32:30 -06:00
}
2023-02-07 01:32:30 -06:00
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
where
for<'a> C::Key: HashStable<StableHashingContext<'a>>,
{
type Key = C::Key;
type Value = C::Value;
type Cache = C;
#[inline(always)]
fn name(self) -> &'static str {
self.dynamic.name
}
#[inline(always)]
fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
(self.dynamic.cache_on_disk)(tcx, key)
}
#[inline(always)]
fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key>
2023-02-07 01:32:30 -06:00
where
QueryCtxt<'tcx>: 'a,
{
self.dynamic.query_state.apply(&qcx.tcx.query_system.states)
}
#[inline(always)]
fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
where
'tcx: 'a,
{
self.dynamic.query_cache.apply(&qcx.tcx.query_system.caches)
}
#[inline(always)]
fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
(self.dynamic.execute_query)(tcx, key)
}
#[inline(always)]
fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
(self.dynamic.compute)(qcx.tcx, key)
}
#[inline(always)]
fn try_load_from_disk(
self,
qcx: QueryCtxt<'tcx>,
key: &Self::Key,
prev_index: SerializedDepNodeIndex,
index: DepNodeIndex,
) -> Option<Self::Value> {
if self.dynamic.can_load_from_disk {
(self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
} else {
None
}
}
#[inline]
fn loadable_from_disk(
self,
qcx: QueryCtxt<'tcx>,
key: &Self::Key,
index: SerializedDepNodeIndex,
) -> bool {
(self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
}
fn value_from_cycle_error(
self,
tcx: TyCtxt<'tcx>,
cycle: &[QueryInfo],
2023-08-27 16:32:55 -05:00
guar: ErrorGuaranteed,
2023-02-07 01:32:30 -06:00
) -> Self::Value {
2023-08-27 16:32:55 -05:00
(self.dynamic.value_from_cycle_error)(tcx, cycle, guar)
2023-02-07 01:32:30 -06:00
}
#[inline(always)]
fn format_value(self) -> fn(&Self::Value) -> String {
self.dynamic.format_value
}
#[inline(always)]
fn anon(self) -> bool {
ANON
}
#[inline(always)]
fn eval_always(self) -> bool {
self.dynamic.eval_always
}
#[inline(always)]
fn depth_limit(self) -> bool {
DEPTH_LIMIT
}
#[inline(always)]
fn feedable(self) -> bool {
FEEDABLE
}
#[inline(always)]
fn dep_kind(self) -> DepKind {
self.dynamic.dep_kind
}
#[inline(always)]
fn handle_cycle_error(self) -> HandleCycleError {
self.dynamic.handle_cycle_error
}
#[inline(always)]
fn hash_result(self) -> HashResult<Self::Value> {
self.dynamic.hash_result
}
}
2023-02-07 01:32:30 -06:00
/// This is implemented per query. It allows restoring query values from their erased state
/// and constructing a QueryConfig.
trait QueryConfigRestored<'tcx> {
type RestoredValue;
type Config: QueryConfig<QueryCtxt<'tcx>>;
const NAME: &'static &'static str;
2023-02-07 01:32:30 -06:00
fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
-> Self::RestoredValue;
}
pub fn query_system<'tcx>(
2023-03-25 03:46:19 -05:00
local_providers: Providers,
extern_providers: ExternProviders,
2023-02-07 01:32:30 -06:00
on_disk_cache: Option<OnDiskCache<'tcx>>,
incremental: bool,
2023-02-07 01:32:30 -06:00
) -> QuerySystem<'tcx> {
QuerySystem {
states: Default::default(),
arenas: Default::default(),
caches: Default::default(),
dynamic_queries: dynamic_queries(),
on_disk_cache,
fns: QuerySystemFns {
engine: engine(incremental),
2023-02-07 01:32:30 -06:00
local_providers,
extern_providers,
encode_query_results: encode_all_query_results,
try_mark_green: try_mark_green,
},
jobs: AtomicU64::new(1),
}
}
2023-02-07 01:32:30 -06:00
rustc_query_append! { define_queries! }