325 lines
11 KiB
Rust
325 lines
11 KiB
Rust
use crate::dep_graph;
|
|
use crate::hir::exports::Export;
|
|
use crate::hir::map;
|
|
use crate::infer::canonical::{self, Canonical};
|
|
use crate::lint::LintLevelMap;
|
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
|
use crate::middle::cstore::{CrateDepKind, CrateSource};
|
|
use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
|
|
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
|
use crate::middle::lib_features::LibFeatures;
|
|
use crate::middle::privacy::AccessLevels;
|
|
use crate::middle::region;
|
|
use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
|
|
use crate::middle::stability::{self, DeprecationEntry};
|
|
use crate::mir;
|
|
use crate::mir::interpret::GlobalId;
|
|
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
|
|
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
|
use crate::mir::mono::CodegenUnit;
|
|
use crate::traits::query::{
|
|
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
|
|
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
|
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
|
|
};
|
|
use crate::traits::query::{
|
|
DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
|
|
OutlivesBound,
|
|
};
|
|
use crate::traits::specialization_graph;
|
|
use crate::traits::{self, ImplSource};
|
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
|
use crate::ty::util::AlwaysRequiresDrop;
|
|
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
|
use rustc_data_structures::stable_hasher::StableVec;
|
|
use rustc_data_structures::steal::Steal;
|
|
use rustc_data_structures::svh::Svh;
|
|
use rustc_data_structures::sync::Lrc;
|
|
use rustc_errors::{ErrorReported, Handler};
|
|
use rustc_hir as hir;
|
|
use rustc_hir::def::DefKind;
|
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
|
|
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
|
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
|
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
|
|
use rustc_serialize::opaque;
|
|
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
|
use rustc_session::utils::NativeLibKind;
|
|
use rustc_session::CrateDisambiguator;
|
|
use rustc_target::spec::PanicStrategy;
|
|
|
|
use rustc_ast as ast;
|
|
use rustc_attr as attr;
|
|
use rustc_span::symbol::Symbol;
|
|
use rustc_span::{Span, DUMMY_SP};
|
|
use std::collections::BTreeMap;
|
|
use std::ops::Deref;
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
pub(crate) use rustc_query_system::query::QueryJobId;
|
|
use rustc_query_system::query::*;
|
|
|
|
pub mod on_disk_cache;
|
|
pub use self::on_disk_cache::OnDiskCache;
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct TyCtxtAt<'tcx> {
|
|
pub tcx: TyCtxt<'tcx>,
|
|
pub span: Span,
|
|
}
|
|
|
|
impl Deref for TyCtxtAt<'tcx> {
|
|
type Target = TyCtxt<'tcx>;
|
|
#[inline(always)]
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.tcx
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct TyCtxtEnsure<'tcx> {
|
|
pub tcx: TyCtxt<'tcx>,
|
|
}
|
|
|
|
impl TyCtxt<'tcx> {
|
|
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
|
|
/// are executed instead of just returning their results.
|
|
#[inline(always)]
|
|
pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
|
|
TyCtxtEnsure { tcx: self }
|
|
}
|
|
|
|
/// Returns a transparent wrapper for `TyCtxt` which uses
|
|
/// `span` as the location of queries performed through it.
|
|
#[inline(always)]
|
|
pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
|
|
TyCtxtAt { tcx: self, span }
|
|
}
|
|
|
|
pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
|
|
self.queries.try_mark_green(self, dep_node)
|
|
}
|
|
}
|
|
|
|
macro_rules! query_helper_param_ty {
|
|
(DefId) => { impl IntoQueryParam<DefId> };
|
|
($K:ty) => { $K };
|
|
}
|
|
|
|
macro_rules! query_storage {
|
|
([][$K:ty, $V:ty]) => {
|
|
<DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
|
|
};
|
|
([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
|
|
<$ty as CacheSelector<$K, $V>>::Cache
|
|
};
|
|
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
|
|
query_storage!([$($($modifiers)*)*][$($args)*])
|
|
};
|
|
}
|
|
|
|
macro_rules! define_callbacks {
|
|
(<$tcx:tt>
|
|
$($(#[$attr:meta])*
|
|
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
|
|
|
|
// HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
|
|
// below, but using type aliases instead of associated types, to bypass
|
|
// the limitations around normalizing under HRTB - for example, this:
|
|
// `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
|
|
// doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
|
|
// This is primarily used by the `provide!` macro in `rustc_metadata`.
|
|
#[allow(nonstandard_style, unused_lifetimes)]
|
|
pub mod query_keys {
|
|
use super::*;
|
|
|
|
$(pub type $name<$tcx> = $($K)*;)*
|
|
}
|
|
#[allow(nonstandard_style, unused_lifetimes)]
|
|
pub mod query_values {
|
|
use super::*;
|
|
|
|
$(pub type $name<$tcx> = $V;)*
|
|
}
|
|
#[allow(nonstandard_style, unused_lifetimes)]
|
|
pub mod query_storage {
|
|
use super::*;
|
|
|
|
$(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
|
|
}
|
|
#[allow(nonstandard_style, unused_lifetimes)]
|
|
pub mod query_stored {
|
|
use super::*;
|
|
|
|
$(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct QueryCaches<$tcx> {
|
|
$($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
|
|
}
|
|
|
|
impl TyCtxtEnsure<$tcx> {
|
|
$($(#[$attr])*
|
|
#[inline(always)]
|
|
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
|
|
let key = key.into_query_param();
|
|
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});
|
|
|
|
let lookup = match cached {
|
|
Ok(()) => return,
|
|
Err(lookup) => lookup,
|
|
};
|
|
|
|
self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
|
|
})*
|
|
}
|
|
|
|
impl TyCtxt<$tcx> {
|
|
$($(#[$attr])*
|
|
#[inline(always)]
|
|
#[must_use]
|
|
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
|
|
{
|
|
self.at(DUMMY_SP).$name(key)
|
|
})*
|
|
}
|
|
|
|
impl TyCtxtAt<$tcx> {
|
|
$($(#[$attr])*
|
|
#[inline(always)]
|
|
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
|
|
{
|
|
let key = key.into_query_param();
|
|
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
|
|
value.clone()
|
|
});
|
|
|
|
let lookup = match cached {
|
|
Ok(value) => return value,
|
|
Err(lookup) => lookup,
|
|
};
|
|
|
|
self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
|
|
})*
|
|
}
|
|
|
|
pub struct Providers {
|
|
$(pub $name: for<'tcx> fn(
|
|
TyCtxt<'tcx>,
|
|
query_keys::$name<'tcx>,
|
|
) -> query_values::$name<'tcx>,)*
|
|
}
|
|
|
|
impl Default for Providers {
|
|
fn default() -> Self {
|
|
Providers {
|
|
$($name: |_, key| bug!(
|
|
"`tcx.{}({:?})` unsupported by its crate",
|
|
stringify!($name), key
|
|
),)*
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Copy for Providers {}
|
|
impl Clone for Providers {
|
|
fn clone(&self) -> Self { *self }
|
|
}
|
|
|
|
pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
|
|
#[cfg(parallel_compiler)]
|
|
unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry);
|
|
|
|
fn encode_query_results(
|
|
&'tcx self,
|
|
tcx: TyCtxt<'tcx>,
|
|
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
|
|
query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
|
|
) -> opaque::FileEncodeResult;
|
|
|
|
fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>);
|
|
|
|
fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
|
|
|
|
fn try_print_query_stack(
|
|
&'tcx self,
|
|
tcx: TyCtxt<'tcx>,
|
|
query: Option<QueryJobId<dep_graph::DepKind>>,
|
|
handler: &Handler,
|
|
num_frames: Option<usize>,
|
|
) -> usize;
|
|
|
|
$($(#[$attr])*
|
|
fn $name(
|
|
&'tcx self,
|
|
tcx: TyCtxt<$tcx>,
|
|
span: Span,
|
|
key: query_keys::$name<$tcx>,
|
|
lookup: QueryLookup,
|
|
mode: QueryMode,
|
|
) -> Option<query_stored::$name<$tcx>>;)*
|
|
}
|
|
};
|
|
}
|
|
|
|
// Each of these queries corresponds to a function pointer field in the
|
|
// `Providers` struct for requesting a value of that type, and a method
|
|
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
|
|
// which memoizes and does dep-graph tracking, wrapping around the actual
|
|
// `Providers` that the driver creates (using several `rustc_*` crates).
|
|
//
|
|
// The result type of each query must implement `Clone`, and additionally
|
|
// `ty::query::values::Value`, which produces an appropriate placeholder
|
|
// (error) value if the query resulted in a query cycle.
|
|
// Queries marked with `fatal_cycle` do not need the latter implementation,
|
|
// as they will raise an fatal error on query cycles instead.
|
|
|
|
rustc_query_append! { [define_callbacks!][<'tcx>] }
|
|
|
|
mod sealed {
|
|
use super::{DefId, LocalDefId};
|
|
|
|
/// An analogue of the `Into` trait that's intended only for query paramaters.
|
|
///
|
|
/// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
|
|
/// user call `to_def_id` to convert between them everywhere else.
|
|
pub trait IntoQueryParam<P> {
|
|
fn into_query_param(self) -> P;
|
|
}
|
|
|
|
impl<P> IntoQueryParam<P> for P {
|
|
#[inline(always)]
|
|
fn into_query_param(self) -> P {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl IntoQueryParam<DefId> for LocalDefId {
|
|
#[inline(always)]
|
|
fn into_query_param(self) -> DefId {
|
|
self.to_def_id()
|
|
}
|
|
}
|
|
}
|
|
|
|
use sealed::IntoQueryParam;
|
|
|
|
impl TyCtxt<'tcx> {
|
|
pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
|
|
let def_id = def_id.into_query_param();
|
|
self.opt_def_kind(def_id)
|
|
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
|
|
}
|
|
}
|
|
|
|
impl TyCtxtAt<'tcx> {
|
|
pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
|
|
let def_id = def_id.into_query_param();
|
|
self.opt_def_kind(def_id)
|
|
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
|
|
}
|
|
}
|