mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Add a TaggedQueryKey to identify a query instance
This commit is contained in:
@@ -4575,7 +4575,6 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_thread_pool",
|
||||
"tracing",
|
||||
|
||||
@@ -7,21 +7,15 @@
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::query::plumbing::CycleError;
|
||||
use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
|
||||
use crate::query::stack::QueryStackFrame;
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
/// Represents a span and a query key.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryInfo<I> {
|
||||
pub struct QueryInfo<'tcx> {
|
||||
/// The span corresponding to the reason for which this query was required.
|
||||
pub span: Span,
|
||||
pub frame: QueryStackFrame<I>,
|
||||
}
|
||||
|
||||
impl<'tcx> QueryInfo<QueryStackDeferred<'tcx>> {
|
||||
pub(crate) fn lift(&self) -> QueryInfo<QueryStackFrameExtra> {
|
||||
QueryInfo { span: self.span, frame: self.frame.lift() }
|
||||
}
|
||||
pub frame: QueryStackFrame<'tcx>,
|
||||
}
|
||||
|
||||
/// A value uniquely identifying an active query job.
|
||||
@@ -74,7 +68,7 @@ pub struct QueryWaiter<'tcx> {
|
||||
pub query: Option<QueryJobId>,
|
||||
pub condvar: Condvar,
|
||||
pub span: Span,
|
||||
pub cycle: Mutex<Option<CycleError<QueryStackDeferred<'tcx>>>>,
|
||||
pub cycle: Mutex<Option<CycleError<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -94,7 +88,7 @@ pub fn wait_on(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
query: Option<QueryJobId>,
|
||||
span: Span,
|
||||
) -> Result<(), CycleError<QueryStackDeferred<'tcx>>> {
|
||||
) -> Result<(), CycleError<'tcx>> {
|
||||
let mut waiters_guard = self.waiters.lock();
|
||||
let Some(waiters) = &mut *waiters_guard else {
|
||||
return Ok(()); // already complete
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode,
|
||||
QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
|
||||
};
|
||||
pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
|
||||
pub use self::stack::QueryStackFrame;
|
||||
pub use crate::queries::Providers;
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
|
||||
use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables};
|
||||
use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
|
||||
use crate::query::on_disk_cache::OnDiskCache;
|
||||
use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
|
||||
use crate::query::stack::QueryStackFrame;
|
||||
use crate::query::{QueryCache, QueryInfo, QueryJob};
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
@@ -60,19 +60,10 @@ pub enum CycleErrorHandling {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CycleError<I = QueryStackFrameExtra> {
|
||||
pub struct CycleError<'tcx> {
|
||||
/// The query and related span that uses the cycle.
|
||||
pub usage: Option<(Span, QueryStackFrame<I>)>,
|
||||
pub cycle: Vec<QueryInfo<I>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
|
||||
pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
|
||||
CycleError {
|
||||
usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
|
||||
cycle: self.cycle.iter().map(|info| info.lift()).collect(),
|
||||
}
|
||||
}
|
||||
pub usage: Option<(Span, QueryStackFrame<'tcx>)>,
|
||||
pub cycle: Vec<QueryInfo<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -139,16 +130,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
|
||||
pub value_from_cycle_error: fn(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: C::Key,
|
||||
cycle_error: CycleError,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> C::Value,
|
||||
pub format_value: fn(&C::Value) -> String,
|
||||
|
||||
/// Formats a human-readable description of this query and its key, as
|
||||
/// specified by the `desc` query modifier.
|
||||
///
|
||||
/// Used when reporting query cycle errors and similar problems.
|
||||
pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
|
||||
pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>,
|
||||
|
||||
/// Function pointer that is called by the query methods on [`TyCtxt`] and
|
||||
/// friends[^1], after they have checked the in-memory cache and found no
|
||||
@@ -524,6 +511,69 @@ pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
|
||||
}
|
||||
)*
|
||||
|
||||
/// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a number.
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TaggedQueryKey<'tcx> {
|
||||
$(
|
||||
$name($name::Key<'tcx>),
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'tcx> TaggedQueryKey<'tcx> {
|
||||
/// Formats a human-readable description of this query and its key, as
|
||||
/// specified by the `desc` query modifier.
|
||||
///
|
||||
/// Used when reporting query cycle errors and similar problems.
|
||||
pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
let (name, description) = ty::print::with_no_queries!(match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => (stringify!($name), _description_fns::$name(tcx, *key)),
|
||||
)*
|
||||
});
|
||||
if tcx.sess.verbose_internals() {
|
||||
format!("{description} [{name:?}]")
|
||||
} else {
|
||||
description
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the default span for this query if `span` is a dummy span.
|
||||
pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
|
||||
if !span.is_dummy() {
|
||||
return span
|
||||
}
|
||||
if let TaggedQueryKey::def_span(..) = self {
|
||||
// The `def_span` query is used to calculate `default_span`,
|
||||
// so exit to avoid infinite recursion.
|
||||
return DUMMY_SP
|
||||
}
|
||||
match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => crate::query::QueryKey::default_span(key, tcx),
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
|
||||
// This is used to reduce code generation as it
|
||||
// can be reused for queries with the same key type.
|
||||
fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
|
||||
key.key_as_def_id().and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
|
||||
}
|
||||
|
||||
if let TaggedQueryKey::def_kind(..) = self {
|
||||
// Try to avoid infinite recursion.
|
||||
return None
|
||||
}
|
||||
match self {
|
||||
$(
|
||||
TaggedQueryKey::$name(key) => inner(key, tcx),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds a `QueryVTable` for each query.
|
||||
pub struct QueryVTables<'tcx> {
|
||||
$(
|
||||
|
||||
@@ -1,106 +1,18 @@
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::dep_graph::DepKind;
|
||||
use crate::queries::TaggedQueryKey;
|
||||
|
||||
/// Description of a frame in the query stack.
|
||||
///
|
||||
/// This is mostly used in case of cycles for error reporting.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryStackFrame<I> {
|
||||
/// This field initially stores a `QueryStackDeferred` during collection,
|
||||
/// but can later be changed to `QueryStackFrameExtra` containing concrete information
|
||||
/// by calling `lift`. This is done so that collecting query does not need to invoke
|
||||
/// queries, instead `lift` will call queries in a more appropriate location.
|
||||
pub info: I,
|
||||
|
||||
pub struct QueryStackFrame<'tcx> {
|
||||
pub tagged_key: TaggedQueryKey<'tcx>,
|
||||
pub dep_kind: DepKind,
|
||||
pub def_id: Option<DefId>,
|
||||
/// A def-id that is extracted from a `Ty` in a query key
|
||||
pub def_id_for_ty_in_cycle: Option<DefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
info: QueryStackDeferred<'tcx>,
|
||||
dep_kind: DepKind,
|
||||
def_id: Option<DefId>,
|
||||
def_id_for_ty_in_cycle: Option<DefId>,
|
||||
) -> Self {
|
||||
Self { info, def_id, dep_kind, def_id_for_ty_in_cycle }
|
||||
}
|
||||
|
||||
pub fn lift(&self) -> QueryStackFrame<QueryStackFrameExtra> {
|
||||
QueryStackFrame {
|
||||
info: self.info.extract(),
|
||||
dep_kind: self.dep_kind,
|
||||
def_id: self.def_id,
|
||||
def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryStackFrameExtra {
|
||||
pub description: String,
|
||||
pub span: Option<Span>,
|
||||
pub def_kind: Option<DefKind>,
|
||||
}
|
||||
|
||||
impl QueryStackFrameExtra {
|
||||
#[inline]
|
||||
pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
|
||||
Self { description, span, def_kind }
|
||||
}
|
||||
|
||||
// FIXME(eddyb) Get more valid `Span`s on queries.
|
||||
#[inline]
|
||||
pub fn default_span(&self, span: Span) -> Span {
|
||||
if !span.is_dummy() {
|
||||
return span;
|
||||
}
|
||||
self.span.unwrap_or(span)
|
||||
}
|
||||
}
|
||||
|
||||
/// Track a 'side effect' for a particular query.
|
||||
/// This is used to hold a closure which can create `QueryStackFrameExtra`.
|
||||
#[derive(Clone)]
|
||||
pub struct QueryStackDeferred<'tcx> {
|
||||
_dummy: PhantomData<&'tcx ()>,
|
||||
|
||||
// `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
|
||||
// access it in the destructor.
|
||||
extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
|
||||
}
|
||||
|
||||
impl<'tcx> QueryStackDeferred<'tcx> {
|
||||
pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
|
||||
context: C,
|
||||
extract: fn(C) -> QueryStackFrameExtra,
|
||||
) -> Self {
|
||||
let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
|
||||
Arc::new(move || extract(context));
|
||||
// SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
|
||||
// captured variable is `context` which is Copy and cannot have a destructor.
|
||||
Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
|
||||
}
|
||||
|
||||
pub fn extract(&self) -> QueryStackFrameExtra {
|
||||
(self.extract)()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for QueryStackDeferred<'tcx> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("QueryStackDeferred")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_thread_pool = { path = "../rustc_thread_pool" }
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -48,7 +48,7 @@ pub fn collect_active_jobs_from_all_queries<'tcx>(
|
||||
let mut complete = true;
|
||||
|
||||
for_each_query_vtable!(ALL, tcx, |query| {
|
||||
let res = gather_active_jobs(query, tcx, require_complete, &mut job_map_out);
|
||||
let res = gather_active_jobs(query, require_complete, &mut job_map_out);
|
||||
if res.is_none() {
|
||||
complete = false;
|
||||
}
|
||||
@@ -66,7 +66,6 @@ pub fn collect_active_jobs_from_all_queries<'tcx>(
|
||||
/// grep for.)
|
||||
fn gather_active_jobs<'tcx, C>(
|
||||
query: &'tcx QueryVTable<'tcx, C>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
require_complete: bool,
|
||||
job_map_out: &mut QueryJobMap<'tcx>, // Out-param; job info is gathered into this map
|
||||
) -> Option<()>
|
||||
@@ -113,7 +112,7 @@ fn gather_active_jobs<'tcx, C>(
|
||||
// Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call
|
||||
// queries leading to a deadlock.
|
||||
for (key, job) in active {
|
||||
let frame = crate::plumbing::create_deferred_query_stack_frame(tcx, query, key);
|
||||
let frame = crate::plumbing::create_query_stack_frame(query, key);
|
||||
job_map_out.insert(job.id, QueryJobInfo { frame, job });
|
||||
}
|
||||
|
||||
@@ -126,9 +125,9 @@ fn mk_cycle<'tcx, C: QueryCache>(
|
||||
query: &'tcx QueryVTable<'tcx, C>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: C::Key,
|
||||
cycle_error: CycleError,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
) -> C::Value {
|
||||
let error = report_cycle(tcx.sess, &cycle_error);
|
||||
let error = report_cycle(tcx, &cycle_error);
|
||||
match query.cycle_error_handling {
|
||||
CycleErrorHandling::Error => {
|
||||
let guar = error.emit();
|
||||
@@ -231,7 +230,7 @@ fn cycle_error<'tcx, C: QueryCache>(
|
||||
.expect("failed to collect active queries");
|
||||
|
||||
let error = find_cycle_in_stack(try_execute, job_map, ¤t_query_job(), span);
|
||||
(mk_cycle(query, tcx, key, error.lift()), None)
|
||||
(mk_cycle(query, tcx, key, error), None)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -276,7 +275,7 @@ fn wait_for_query<'tcx, C: QueryCache>(
|
||||
|
||||
(v, Some(index))
|
||||
}
|
||||
Err(cycle) => (mk_cycle(query, tcx, key, cycle.lift()), None),
|
||||
Err(cycle) => (mk_cycle(query, tcx, key, cycle), None),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,11 @@ pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) {
|
||||
|tcx, _, cycle, guar| erase_val(layout_of(tcx, cycle, guar));
|
||||
}
|
||||
|
||||
pub(crate) fn default<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError, query_name: &str) -> ! {
|
||||
pub(crate) fn default<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
query_name: &str,
|
||||
) -> ! {
|
||||
let Some(guar) = tcx.sess.dcx().has_errors() else {
|
||||
bug!(
|
||||
"`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}",
|
||||
@@ -82,7 +86,7 @@ fn fn_sig<'tcx>(
|
||||
|
||||
fn check_representability<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cycle_error: CycleError,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> ! {
|
||||
let mut item_and_field_ids = Vec::new();
|
||||
@@ -91,7 +95,7 @@ fn check_representability<'tcx>(
|
||||
if info.frame.dep_kind == DepKind::check_representability
|
||||
&& let Some(field_id) = info.frame.def_id
|
||||
&& let Some(field_id) = field_id.as_local()
|
||||
&& let Some(DefKind::Field) = info.frame.info.def_kind
|
||||
&& let Some(DefKind::Field) = info.frame.tagged_key.def_kind(tcx)
|
||||
{
|
||||
let parent_id = tcx.parent(field_id.to_def_id());
|
||||
let item_id = match tcx.def_kind(parent_id) {
|
||||
@@ -118,7 +122,7 @@ fn check_representability<'tcx>(
|
||||
|
||||
fn variances_of<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cycle_error: CycleError,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> &'tcx [ty::Variance] {
|
||||
search_for_cycle_permutation(
|
||||
@@ -164,7 +168,7 @@ fn search_for_cycle_permutation<Q, T>(
|
||||
|
||||
fn layout_of<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cycle_error: CycleError,
|
||||
cycle_error: CycleError<'tcx>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> Result<TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
|
||||
let diag = search_for_cycle_permutation(
|
||||
@@ -205,7 +209,7 @@ fn layout_of<'tcx>(
|
||||
continue;
|
||||
};
|
||||
let frame_span =
|
||||
info.frame.info.default_span(cycle[(i + 1) % cycle.len()].span);
|
||||
info.frame.tagged_key.default_span(tcx, cycle[(i + 1) % cycle.len()].span);
|
||||
if frame_span.is_dummy() {
|
||||
continue;
|
||||
}
|
||||
@@ -239,7 +243,7 @@ fn layout_of<'tcx>(
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
},
|
||||
|| report_cycle(tcx.sess, &cycle_error),
|
||||
|| report_cycle(tcx, &cycle_error),
|
||||
);
|
||||
|
||||
let guar = diag.emit();
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
use rustc_errors::{Diag, DiagCtxtHandle};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::query::{
|
||||
CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame,
|
||||
QueryWaiter,
|
||||
CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter,
|
||||
};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
|
||||
use crate::execution::collect_active_jobs_from_all_queries;
|
||||
@@ -31,7 +29,7 @@ pub(crate) fn insert(&mut self, id: QueryJobId, info: QueryJobInfo<'tcx>) {
|
||||
self.map.insert(id, info);
|
||||
}
|
||||
|
||||
fn frame_of(&self, id: QueryJobId) -> &QueryStackFrame<QueryStackDeferred<'tcx>> {
|
||||
fn frame_of(&self, id: QueryJobId) -> &QueryStackFrame<'tcx> {
|
||||
&self.map[&id].frame
|
||||
}
|
||||
|
||||
@@ -50,7 +48,7 @@ fn latch_of(&self, id: QueryJobId) -> Option<&QueryLatch<'tcx>> {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct QueryJobInfo<'tcx> {
|
||||
pub(crate) frame: QueryStackFrame<QueryStackDeferred<'tcx>>,
|
||||
pub(crate) frame: QueryStackFrame<'tcx>,
|
||||
pub(crate) job: QueryJob<'tcx>,
|
||||
}
|
||||
|
||||
@@ -59,7 +57,7 @@ pub(crate) fn find_cycle_in_stack<'tcx>(
|
||||
job_map: QueryJobMap<'tcx>,
|
||||
current_job: &Option<QueryJobId>,
|
||||
span: Span,
|
||||
) -> CycleError<QueryStackDeferred<'tcx>> {
|
||||
) -> CycleError<'tcx> {
|
||||
// Find the waitee amongst `current_job` parents
|
||||
let mut cycle = Vec::new();
|
||||
let mut current_job = Option::clone(current_job);
|
||||
@@ -395,12 +393,12 @@ pub fn print_query_stack<'tcx>(
|
||||
let Some(query_info) = job_map.map.get(&query) else {
|
||||
break;
|
||||
};
|
||||
let query_extra = query_info.frame.info.extract();
|
||||
let description = query_info.frame.tagged_key.description(tcx);
|
||||
if Some(count_printed) < limit_frames || limit_frames.is_none() {
|
||||
// Only print to stderr as many stack frames as `num_frames` when present.
|
||||
dcx.struct_failure_note(format!(
|
||||
"#{} [{:?}] {}",
|
||||
count_printed, query_info.frame.dep_kind, query_extra.description
|
||||
count_printed, query_info.frame.dep_kind, description
|
||||
))
|
||||
.with_span(query_info.job.span)
|
||||
.emit();
|
||||
@@ -411,7 +409,7 @@ pub fn print_query_stack<'tcx>(
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"#{} [{:?}] {}",
|
||||
count_total, query_info.frame.dep_kind, query_extra.description
|
||||
count_total, query_info.frame.dep_kind, description
|
||||
);
|
||||
}
|
||||
|
||||
@@ -427,18 +425,18 @@ pub fn print_query_stack<'tcx>(
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
pub(crate) fn report_cycle<'a>(
|
||||
sess: &'a Session,
|
||||
CycleError { usage, cycle: stack }: &CycleError,
|
||||
) -> Diag<'a> {
|
||||
pub(crate) fn report_cycle<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
CycleError { usage, cycle: stack }: &CycleError<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
assert!(!stack.is_empty());
|
||||
|
||||
let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span);
|
||||
let span = stack[0].frame.tagged_key.default_span(tcx, stack[1 % stack.len()].span);
|
||||
|
||||
let mut cycle_stack = Vec::new();
|
||||
|
||||
use crate::error::StackCount;
|
||||
let stack_bottom = stack[0].frame.info.description.to_owned();
|
||||
let stack_bottom = stack[0].frame.tagged_key.description(tcx);
|
||||
let stack_count = if stack.len() == 1 {
|
||||
StackCount::Single { stack_bottom: stack_bottom.clone() }
|
||||
} else {
|
||||
@@ -447,27 +445,32 @@ pub(crate) fn report_cycle<'a>(
|
||||
|
||||
for i in 1..stack.len() {
|
||||
let frame = &stack[i].frame;
|
||||
let span = frame.info.default_span(stack[(i + 1) % stack.len()].span);
|
||||
let span = frame.tagged_key.default_span(tcx, stack[(i + 1) % stack.len()].span);
|
||||
cycle_stack
|
||||
.push(crate::error::CycleStack { span, desc: frame.info.description.to_owned() });
|
||||
.push(crate::error::CycleStack { span, desc: frame.tagged_key.description(tcx) });
|
||||
}
|
||||
|
||||
let mut cycle_usage = None;
|
||||
if let Some((span, ref query)) = *usage {
|
||||
cycle_usage = Some(crate::error::CycleUsage {
|
||||
span: query.info.default_span(span),
|
||||
usage: query.info.description.to_string(),
|
||||
span: query.tagged_key.default_span(tcx, span),
|
||||
usage: query.tagged_key.description(tcx),
|
||||
});
|
||||
}
|
||||
|
||||
let alias =
|
||||
if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) {
|
||||
Some(crate::error::Alias::Ty)
|
||||
} else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) {
|
||||
Some(crate::error::Alias::Trait)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let alias = if stack
|
||||
.iter()
|
||||
.all(|entry| matches!(entry.frame.tagged_key.def_kind(tcx), Some(DefKind::TyAlias)))
|
||||
{
|
||||
Some(crate::error::Alias::Ty)
|
||||
} else if stack
|
||||
.iter()
|
||||
.all(|entry| entry.frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
|
||||
{
|
||||
Some(crate::error::Alias::Trait)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cycle_diag = crate::error::Cycle {
|
||||
span,
|
||||
@@ -479,5 +482,5 @@ pub(crate) fn report_cycle<'a>(
|
||||
note_span: (),
|
||||
};
|
||||
|
||||
sess.dcx().create_err(cycle_diag)
|
||||
tcx.sess.dcx().create_err(cycle_diag)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
use rustc_data_structures::sync::AtomicU64;
|
||||
use rustc_middle::dep_graph;
|
||||
use rustc_middle::queries::{self, ExternProviders, Providers};
|
||||
use rustc_middle::queries::{self, ExternProviders, Providers, TaggedQueryKey};
|
||||
use rustc_middle::query::on_disk_cache::OnDiskCache;
|
||||
use rustc_middle::query::plumbing::{QuerySystem, QueryVTable};
|
||||
use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode};
|
||||
|
||||
@@ -18,14 +18,10 @@
|
||||
AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
|
||||
};
|
||||
use rustc_middle::query::plumbing::QueryVTable;
|
||||
use rustc_middle::query::{
|
||||
QueryCache, QueryJobId, QueryKey, QueryMode, QueryStackDeferred, QueryStackFrame,
|
||||
QueryStackFrameExtra, erase,
|
||||
};
|
||||
use rustc_middle::query::{QueryCache, QueryJobId, QueryKey, QueryMode, QueryStackFrame, erase};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::codec::TyEncoder;
|
||||
use rustc_middle::ty::print::with_reduced_queries;
|
||||
use rustc_middle::ty::tls::{self, ImplicitCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
@@ -47,7 +43,7 @@ fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) {
|
||||
|
||||
tcx.sess.dcx().emit_fatal(QueryOverflow {
|
||||
span: info.job.span,
|
||||
note: QueryOverflowNote { desc: info.frame.info.extract().description, depth },
|
||||
note: QueryOverflowNote { desc: info.frame.tagged_key.description(tcx), depth },
|
||||
suggested_limit,
|
||||
crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||
});
|
||||
@@ -90,60 +86,23 @@ pub(crate) fn start_query<R>(
|
||||
})
|
||||
}
|
||||
|
||||
/// The deferred part of a deferred query stack frame.
|
||||
fn mk_query_stack_frame_extra<'tcx, Cache>(
|
||||
(tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key),
|
||||
) -> QueryStackFrameExtra
|
||||
where
|
||||
Cache: QueryCache,
|
||||
Cache::Key: QueryKey,
|
||||
{
|
||||
let def_id = key.key_as_def_id();
|
||||
|
||||
// If reduced queries are requested, we may be printing a query stack due
|
||||
// to a panic. Avoid using `default_span` and `def_kind` in that case.
|
||||
let reduce_queries = with_reduced_queries();
|
||||
|
||||
// Avoid calling queries while formatting the description
|
||||
let description = ty::print::with_no_queries!((vtable.description_fn)(tcx, key));
|
||||
let description = if tcx.sess.verbose_internals() {
|
||||
format!("{description} [{name:?}]", name = vtable.name)
|
||||
} else {
|
||||
description
|
||||
};
|
||||
let span = if vtable.dep_kind == DepKind::def_span || reduce_queries {
|
||||
// The `def_span` query is used to calculate `default_span`,
|
||||
// so exit to avoid infinite recursion.
|
||||
None
|
||||
} else {
|
||||
Some(key.default_span(tcx))
|
||||
};
|
||||
|
||||
let def_kind = if vtable.dep_kind == DepKind::def_kind || reduce_queries {
|
||||
// Try to avoid infinite recursion.
|
||||
None
|
||||
} else {
|
||||
def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
|
||||
};
|
||||
QueryStackFrameExtra::new(description, span, def_kind)
|
||||
}
|
||||
|
||||
pub(crate) fn create_deferred_query_stack_frame<'tcx, C>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pub(crate) fn create_query_stack_frame<'tcx, C>(
|
||||
vtable: &'tcx QueryVTable<'tcx, C>,
|
||||
key: C::Key,
|
||||
) -> QueryStackFrame<QueryStackDeferred<'tcx>>
|
||||
) -> QueryStackFrame<'tcx>
|
||||
where
|
||||
C: QueryCache<Key: QueryKey + DynSend + DynSync>,
|
||||
QueryVTable<'tcx, C>: DynSync,
|
||||
{
|
||||
let kind = vtable.dep_kind;
|
||||
|
||||
let def_id: Option<DefId> = key.key_as_def_id();
|
||||
let def_id_for_ty_in_cycle: Option<DefId> = key.def_id_for_ty_in_cycle();
|
||||
|
||||
let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra);
|
||||
QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle)
|
||||
QueryStackFrame {
|
||||
tagged_key: (vtable.create_tagged_key)(key),
|
||||
dep_kind: vtable.dep_kind,
|
||||
def_id,
|
||||
def_id_for_ty_in_cycle,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn encode_all_query_results<'tcx>(
|
||||
@@ -500,7 +459,7 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
|
||||
}),
|
||||
|
||||
format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
|
||||
description_fn: $crate::queries::_description_fns::$name,
|
||||
create_tagged_key: TaggedQueryKey::$name,
|
||||
execute_query_fn: if incremental {
|
||||
query_impl::$name::execute_query_incr::__rust_end_short_backtrace
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user