Don't use HasDepContext in DepGraph::with_task
The need for a `HasDepContext` impl on tuples can be avoided by passing the query vtable as part of an argument tuple instead.
This commit is contained in:
parent
fbb34d8c75
commit
db58395a6b
4 changed files with 46 additions and 53 deletions
|
|
@ -268,17 +268,17 @@ impl DepGraph {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>(
|
||||
pub fn with_task<'tcx, A: Debug, R>(
|
||||
&self,
|
||||
key: DepNode,
|
||||
cx: Ctxt,
|
||||
arg: A,
|
||||
task: fn(Ctxt, A) -> R,
|
||||
dep_node: DepNode,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
task_arg: A,
|
||||
task_fn: fn(tcx: TyCtxt<'tcx>, task_arg: A) -> R,
|
||||
hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
|
||||
) -> (R, DepNodeIndex) {
|
||||
match self.data() {
|
||||
Some(data) => data.with_task(key, cx, arg, task, hash_result),
|
||||
None => (task(cx, arg), self.next_virtual_depnode_index()),
|
||||
Some(data) => data.with_task(dep_node, tcx, task_arg, task_fn, hash_result),
|
||||
None => (task_fn(tcx, task_arg), self.next_virtual_depnode_index()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,33 +310,21 @@ impl DepGraphData {
|
|||
/// prevent implicit 'leaks' of tracked state into the task (which
|
||||
/// could then be read without generating correct edges in the
|
||||
/// dep-graph -- see the [rustc dev guide] for more details on
|
||||
/// the dep-graph). To this end, the task function gets exactly two
|
||||
/// pieces of state: the context `cx` and an argument `arg`. Both
|
||||
/// of these bits of state must be of some type that implements
|
||||
/// `DepGraphSafe` and hence does not leak.
|
||||
/// the dep-graph).
|
||||
///
|
||||
/// The choice of two arguments is not fundamental. One argument
|
||||
/// would work just as well, since multiple values can be
|
||||
/// collected using tuples. However, using two arguments works out
|
||||
/// to be quite convenient, since it is common to need a context
|
||||
/// (`cx`) and some argument (e.g., a `DefId` identifying what
|
||||
/// item to process).
|
||||
///
|
||||
/// For cases where you need some other number of arguments:
|
||||
///
|
||||
/// - If you only need one argument, just use `()` for the `arg`
|
||||
/// parameter.
|
||||
/// - If you need 3+ arguments, use a tuple for the
|
||||
/// `arg` parameter.
|
||||
/// Therefore, the task function takes a `TyCtxt`, plus exactly one
|
||||
/// additional argument, `task_arg`. The additional argument type can be
|
||||
/// `()` if no argument is needed, or a tuple if multiple arguments are
|
||||
/// needed.
|
||||
///
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html
|
||||
#[inline(always)]
|
||||
pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>(
|
||||
pub fn with_task<'tcx, A: Debug, R>(
|
||||
&self,
|
||||
key: DepNode,
|
||||
cx: Ctxt,
|
||||
arg: A,
|
||||
task: fn(Ctxt, A) -> R,
|
||||
dep_node: DepNode,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
task_arg: A,
|
||||
task_fn: fn(tcx: TyCtxt<'tcx>, task_arg: A) -> R,
|
||||
hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
|
||||
) -> (R, DepNodeIndex) {
|
||||
// If the following assertion triggers, it can have two reasons:
|
||||
|
|
@ -344,32 +332,28 @@ impl DepGraphData {
|
|||
// in `DepGraph::try_mark_green()`.
|
||||
// 2. Two distinct query keys get mapped to the same `DepNode`
|
||||
// (see for example #48923).
|
||||
self.assert_dep_node_not_yet_allocated_in_current_session(
|
||||
cx.dep_context().sess,
|
||||
&key,
|
||||
|| {
|
||||
format!(
|
||||
"forcing query with already existing `DepNode`\n\
|
||||
- query-key: {arg:?}\n\
|
||||
- dep-node: {key:?}"
|
||||
)
|
||||
},
|
||||
);
|
||||
self.assert_dep_node_not_yet_allocated_in_current_session(tcx.sess, &dep_node, || {
|
||||
format!(
|
||||
"forcing query with already existing `DepNode`\n\
|
||||
- query-key: {task_arg:?}\n\
|
||||
- dep-node: {dep_node:?}"
|
||||
)
|
||||
});
|
||||
|
||||
let with_deps = |task_deps| with_deps(task_deps, || task(cx, arg));
|
||||
let (result, edges) = if cx.dep_context().is_eval_always(key.kind) {
|
||||
let with_deps = |task_deps| with_deps(task_deps, || task_fn(tcx, task_arg));
|
||||
let (result, edges) = if tcx.is_eval_always(dep_node.kind) {
|
||||
(with_deps(TaskDepsRef::EvalAlways), EdgesVec::new())
|
||||
} else {
|
||||
let task_deps = Lock::new(TaskDeps::new(
|
||||
#[cfg(debug_assertions)]
|
||||
Some(key),
|
||||
Some(dep_node),
|
||||
0,
|
||||
));
|
||||
(with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads)
|
||||
};
|
||||
|
||||
let dep_node_index =
|
||||
self.hash_result_and_alloc_node(cx.dep_context(), key, edges, &result, hash_result);
|
||||
self.hash_result_and_alloc_node(tcx, dep_node, edges, &result, hash_result);
|
||||
|
||||
(result, dep_node_index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,6 @@ impl<'tcx> HasDepContext<'tcx> for TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: HasDepContext<'tcx>, Q: Copy> HasDepContext<'tcx> for (T, Q) {
|
||||
fn dep_context(&self) -> TyCtxt<'tcx> {
|
||||
self.0.dep_context()
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the contents of the fingerprint generated by a given query.
|
||||
///
|
||||
/// This is mainly for determining whether and how we can reconstruct a key
|
||||
|
|
|
|||
|
|
@ -475,9 +475,9 @@ fn execute_job_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
|
|||
// Call the query provider.
|
||||
dep_graph_data.with_task(
|
||||
dep_node,
|
||||
(tcx, query),
|
||||
key,
|
||||
|(tcx, query), key| query.invoke_provider(tcx, key),
|
||||
tcx,
|
||||
(query, key),
|
||||
|tcx, (query, key)| query.invoke_provider(tcx, key),
|
||||
query.hash_result(),
|
||||
)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
use rustc_data_structures::sync::AtomicU64;
|
||||
|
|
@ -76,6 +77,20 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Clone
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> fmt::Debug
|
||||
for SemiDynamicQueryDispatcher<'tcx, C, FLAGS>
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// When debug-printing a query dispatcher (e.g. for ICE or tracing),
|
||||
// just print the query name to know what query we're dealing with.
|
||||
// The other fields and flags are probably just unhelpful noise.
|
||||
//
|
||||
// If there is need for a more detailed dump of all flags and fields,
|
||||
// consider writing a separate dump method and calling it explicitly.
|
||||
f.write_str(self.name())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> SemiDynamicQueryDispatcher<'tcx, C, FLAGS> {
|
||||
#[inline(always)]
|
||||
fn name(self) -> &'static str {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue