mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-30 03:57:37 +00:00

It lints against features that are inteded to be internal to the compiler and standard library. Implements MCP #596. We allow `internal_features` in the standard library and compiler as those use many features and this _is_ the standard library from the "internal to the compiler and standard library" after all. Marking some features as internal wasn't exactly the most scientific approach, I just marked some mostly obvious features. While there is a categorization in the macro, it's not very well upheld (should probably be fixed in another PR). We always pass `-Ainternal_features` in the testsuite About 400 UI tests and several other tests use internal features. Instead of throwing the attribute on each one, just always allow them. There's nothing wrong with testing internal features^^
229 lines
6.5 KiB
Rust
229 lines
6.5 KiB
Rust
//! 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)]
|
|
#![feature(const_refs_to_cell)]
|
|
#![feature(min_specialization)]
|
|
#![feature(never_type)]
|
|
#![feature(rustc_attrs)]
|
|
#![recursion_limit = "256"]
|
|
#![allow(rustc::potential_query_instability, unused_parens)]
|
|
#![deny(rustc::untranslatable_diagnostic)]
|
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
|
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
|
|
|
#[macro_use]
|
|
extern crate rustc_middle;
|
|
|
|
use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
|
|
use field_offset::offset_of;
|
|
use rustc_data_structures::stable_hasher::HashStable;
|
|
use rustc_data_structures::sync::AtomicU64;
|
|
use rustc_middle::arena::Arena;
|
|
use rustc_middle::dep_graph::DepNodeIndex;
|
|
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,
|
|
};
|
|
use rustc_middle::query::AsLocalKey;
|
|
use rustc_middle::query::{
|
|
queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
|
|
};
|
|
use rustc_middle::ty::TyCtxt;
|
|
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
|
|
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,
|
|
};
|
|
use rustc_query_system::HandleCycleError;
|
|
use rustc_query_system::Value;
|
|
use rustc_span::Span;
|
|
|
|
#[macro_use]
|
|
mod plumbing;
|
|
pub use crate::plumbing::QueryCtxt;
|
|
|
|
mod profiling_support;
|
|
pub use self::profiling_support::alloc_self_profile_query_strings;
|
|
|
|
struct DynamicConfig<
|
|
'tcx,
|
|
C: QueryCache,
|
|
const ANON: bool,
|
|
const DEPTH_LIMIT: bool,
|
|
const FEEDABLE: bool,
|
|
> {
|
|
dynamic: &'tcx DynamicQuery<'tcx, C>,
|
|
}
|
|
|
|
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 }
|
|
}
|
|
}
|
|
|
|
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, DepKind>
|
|
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<DepKind>],
|
|
) -> Self::Value {
|
|
(self.dynamic.value_from_cycle_error)(tcx, cycle)
|
|
}
|
|
|
|
#[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
|
|
}
|
|
}
|
|
|
|
/// 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>>;
|
|
|
|
fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
|
|
fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
|
|
-> Self::RestoredValue;
|
|
}
|
|
|
|
pub fn query_system<'tcx>(
|
|
local_providers: Providers,
|
|
extern_providers: ExternProviders,
|
|
on_disk_cache: Option<OnDiskCache<'tcx>>,
|
|
incremental: bool,
|
|
) -> QuerySystem<'tcx> {
|
|
QuerySystem {
|
|
states: Default::default(),
|
|
arenas: Default::default(),
|
|
caches: Default::default(),
|
|
dynamic_queries: dynamic_queries(),
|
|
on_disk_cache,
|
|
fns: QuerySystemFns {
|
|
engine: engine(incremental),
|
|
local_providers,
|
|
extern_providers,
|
|
encode_query_results: encode_all_query_results,
|
|
try_mark_green: try_mark_green,
|
|
},
|
|
jobs: AtomicU64::new(1),
|
|
}
|
|
}
|
|
|
|
rustc_query_append! { define_queries! }
|