Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Use a function to create QueryStackDeferred to ensure context is Copy
  • Loading branch information
Zoxc committed Mar 26, 2025
commit 6ca2af6434ec40ae91207628722fe6e731f6f358
74 changes: 41 additions & 33 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//! manage the caches, and so forth.

use std::num::NonZero;
use std::sync::Arc;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{DynSend, DynSync};
Expand Down Expand Up @@ -312,6 +311,45 @@ macro_rules! should_ever_cache_on_disk {
};
}

fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>(
(tcx, key, kind, name, do_describe): (
TyCtxt<'tcx>,
K,
DepKind,
&'static str,
fn(TyCtxt<'tcx>, K) -> String,
),
) -> QueryStackFrameExtra {
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!(do_describe(tcx, key));
let description = if tcx.sess.verbose_internals() {
format!("{description} [{name:?}]")
} else {
description
};
let span = if kind == dep_graph::dep_kinds::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 kind == dep_graph::dep_kinds::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_query_frame<
'tcx,
K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx,
Expand All @@ -324,35 +362,6 @@ pub(crate) fn create_query_frame<
) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
let def_id = key.key_as_def_id();

let extra = move || {
// 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!(do_describe(tcx, key));
let description = if tcx.sess.verbose_internals() {
format!("{description} [{name:?}]")
} else {
description
};
let span = if kind == dep_graph::dep_kinds::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 kind == dep_graph::dep_kinds::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)
};

let hash = || {
tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
Expand All @@ -363,9 +372,8 @@ pub(crate) fn create_query_frame<
};
let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();

// SAFETY: None of the captures in `extra` have destructors that access 'tcx
// as they don't have destructors.
let info = unsafe { QueryStackDeferred::new(Arc::new(extra)) };
let info =
QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra);

QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
}
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_query_system/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,14 @@ pub struct QueryStackDeferred<'tcx> {
}

impl<'tcx> QueryStackDeferred<'tcx> {
/// SAFETY: `extract` may not access 'tcx in its destructor.
pub unsafe fn new(
extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + '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) } }
}

Expand Down
Loading