Make `QueryDispatcher::Qcx` an associated type
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index b628224..d6310b6 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -67,11 +67,11 @@ fn clone(&self) -> Self {
 
 // This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`.
 impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
-    QueryDispatcher<QueryCtxt<'tcx>>
-    for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+    QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
 where
     for<'a> C::Key: HashStable<StableHashingContext<'a>>,
 {
+    type Qcx = QueryCtxt<'tcx>;
     type Key = C::Key;
     type Value = C::Value;
     type Cache = C;
@@ -104,10 +104,7 @@ fn query_state<'a>(
     }
 
     #[inline(always)]
-    fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
-    where
-        'tcx: 'a,
-    {
+    fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache {
         // Safety:
         // This is just manually doing the subfield referencing through pointer math.
         unsafe {
@@ -215,15 +212,13 @@ fn hash_result(self) -> HashResult<Self::Value> {
 /// on the type `rustc_query_impl::query_impl::$name::QueryType`.
 trait QueryDispatcherUnerased<'tcx> {
     type UnerasedValue;
-    type Dispatcher: QueryDispatcher<QueryCtxt<'tcx>>;
+    type Dispatcher: QueryDispatcher<Qcx = QueryCtxt<'tcx>>;
 
     const NAME: &'static &'static str;
 
     fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher;
 
-    fn restore_val(
-        value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value,
-    ) -> Self::UnerasedValue;
+    fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue;
 }
 
 pub fn query_system<'a>(
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6ead03a..0223981 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -414,7 +414,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
 }
 
 pub(crate) fn query_key_hash_verify<'tcx>(
-    query: impl QueryDispatcher<QueryCtxt<'tcx>>,
+    query: impl QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
     qcx: QueryCtxt<'tcx>,
 ) {
     let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
@@ -442,7 +442,7 @@ pub(crate) fn query_key_hash_verify<'tcx>(
 
 fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
 where
-    Q: QueryDispatcher<QueryCtxt<'tcx>>,
+    Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
 {
     debug_assert!(tcx.dep_graph.is_green(&dep_node));
 
@@ -488,7 +488,7 @@ pub(crate) fn try_load_from_disk<'tcx, V>(
 
 fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
 where
-    Q: QueryDispatcher<QueryCtxt<'tcx>>,
+    Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
 {
     // We must avoid ever having to call `force_from_dep_node()` for a
     // `DepNode::codegen_unit`:
@@ -523,8 +523,7 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
 where
     Q: QueryDispatcherUnerased<'tcx>,
 {
-    let fingerprint_style =
-        <Q::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Key::fingerprint_style();
+    let fingerprint_style = <Q::Dispatcher as QueryDispatcher>::Key::fingerprint_style();
 
     if is_anon || !fingerprint_style.reconstructible() {
         return DepKindVTable {
@@ -731,7 +730,7 @@ fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher {
                 }
 
                 #[inline(always)]
-                fn restore_val(value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value) -> Self::UnerasedValue {
+                fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue {
                     restore::<queries::$name::Value<'tcx>>(value)
                 }
             }
diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs
index bba1703..1ca76a7 100644
--- a/compiler/rustc_query_system/src/query/dispatcher.rs
+++ b/compiler/rustc_query_system/src/query/dispatcher.rs
@@ -5,13 +5,18 @@
 use rustc_span::ErrorGuaranteed;
 
 use super::QueryStackFrameExtra;
-use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
+use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex};
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
 use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
 
 pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
 
+/// Unambiguous shorthand for `<This::Qcx as HasDepContext>::DepContext`.
+#[expect(type_alias_bounds)]
+type DepContextOf<This: QueryDispatcher> =
+    <<This as QueryDispatcher>::Qcx as HasDepContext>::DepContext;
+
 /// Trait that can be used as a vtable for a single query, providing operations
 /// and metadata for that query.
 ///
@@ -20,12 +25,15 @@
 /// Those types are not visible from this `rustc_query_system` crate.
 ///
 /// "Dispatcher" should be understood as a near-synonym of "vtable".
-pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
+pub trait QueryDispatcher: Copy {
     fn name(self) -> &'static str;
 
+    /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`.
+    type Qcx: QueryContext;
+
     // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
     // but it isn't necessary.
-    type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Copy + Debug;
+    type Key: DepNodeParams<DepContextOf<Self>> + Eq + Hash + Copy + Debug;
     type Value: Copy;
 
     type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
@@ -33,36 +41,40 @@ pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
     fn format_value(self) -> fn(&Self::Value) -> String;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo>
-    where
-        Qcx: 'a;
+    fn query_state<'a>(
+        self,
+        tcx: Self::Qcx,
+    ) -> &'a QueryState<Self::Key, <Self::Qcx as QueryContext>::QueryInfo>;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache
-    where
-        Qcx: 'a;
+    fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache;
 
-    fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool;
+    fn cache_on_disk(self, tcx: DepContextOf<Self>, key: &Self::Key) -> bool;
 
     // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value;
+    fn execute_query(self, tcx: DepContextOf<Self>, k: Self::Key) -> Self::Value;
 
-    fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value;
+    fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value;
 
     fn try_load_from_disk(
         self,
-        tcx: Qcx,
+        tcx: Self::Qcx,
         key: &Self::Key,
         prev_index: SerializedDepNodeIndex,
         index: DepNodeIndex,
     ) -> Option<Self::Value>;
 
-    fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
+    fn loadable_from_disk(
+        self,
+        qcx: Self::Qcx,
+        key: &Self::Key,
+        idx: SerializedDepNodeIndex,
+    ) -> bool;
 
     /// Synthesize an error value to let compilation continue after a cycle.
     fn value_from_cycle_error(
         self,
-        tcx: Qcx::DepContext,
+        tcx: DepContextOf<Self>,
         cycle_error: &CycleError<QueryStackFrameExtra>,
         guar: ErrorGuaranteed,
     ) -> Self::Value;
@@ -77,7 +89,7 @@ fn value_from_cycle_error(
     fn hash_result(self) -> HashResult<Self::Value>;
 
     // Just here for convenience and checking that the key matches the kind, don't override this.
-    fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode {
+    fn construct_dep_node(self, tcx: DepContextOf<Self>, key: &Self::Key) -> DepNode {
         DepNode::construct(tcx, self.dep_kind(), key)
     }
 }
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 9afad15..7e9f83e 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -19,7 +19,9 @@
 use tracing::instrument;
 
 use super::{QueryDispatcher, QueryStackFrameExtra};
-use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
+use crate::dep_graph::{
+    DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext,
+};
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
 use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
@@ -124,24 +126,22 @@ struct JobOwner<'tcx, K, I>
 
 #[cold]
 #[inline(never)]
-fn mk_cycle<Q, Qcx>(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value
+fn mk_cycle<Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
     handle_cycle_error(query, qcx, &cycle_error, error)
 }
 
-fn handle_cycle_error<Q, Qcx>(
+fn handle_cycle_error<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     cycle_error: &CycleError,
     error: Diag<'_>,
 ) -> Q::Value
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     match query.cycle_error_handling() {
         CycleErrorHandling::Error => {
@@ -272,15 +272,14 @@ pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Va
 
 #[cold]
 #[inline(never)]
-fn cycle_error<Q, Qcx>(
+fn cycle_error<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     try_execute: QueryJobId,
     span: Span,
 ) -> (Q::Value, Option<DepNodeIndex>)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     // Ensure there was no errors collecting all active jobs.
     // We need the complete map to ensure we find a cycle to break.
@@ -291,17 +290,16 @@ fn cycle_error<Q, Qcx>(
 }
 
 #[inline(always)]
-fn wait_for_query<Q, Qcx>(
+fn wait_for_query<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     span: Span,
     key: Q::Key,
-    latch: QueryLatch<Qcx::QueryInfo>,
+    latch: QueryLatch<<Q::Qcx as QueryContext>::QueryInfo>,
     current: Option<QueryJobId>,
 ) -> (Q::Value, Option<DepNodeIndex>)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     // For parallel queries, we'll block and wait until the query running
     // in another thread has completed. Record how long we wait in the
@@ -341,16 +339,15 @@ fn wait_for_query<Q, Qcx>(
 }
 
 #[inline(never)]
-fn try_execute_query<Q, Qcx, const INCR: bool>(
+fn try_execute_query<Q, const INCR: bool>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     span: Span,
     key: Q::Key,
     dep_node: Option<DepNode>,
 ) -> (Q::Value, Option<DepNodeIndex>)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     let state = query.query_state(qcx);
     let key_hash = sharded::make_hash(&key);
@@ -382,7 +379,7 @@ fn try_execute_query<Q, Qcx, const INCR: bool>(
             // Drop the lock before we start executing the query
             drop(state_lock);
 
-            execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node)
+            execute_job::<Q, INCR>(query, qcx, state, key, key_hash, id, dep_node)
         }
         Entry::Occupied(mut entry) => {
             match &mut entry.get_mut().1 {
@@ -411,18 +408,17 @@ fn try_execute_query<Q, Qcx, const INCR: bool>(
 }
 
 #[inline(always)]
-fn execute_job<Q, Qcx, const INCR: bool>(
+fn execute_job<Q, const INCR: bool>(
     query: Q,
-    qcx: Qcx,
-    state: &QueryState<Q::Key, Qcx::QueryInfo>,
+    qcx: Q::Qcx,
+    state: &QueryState<Q::Key, <Q::Qcx as QueryContext>::QueryInfo>,
     key: Q::Key,
     key_hash: u64,
     id: QueryJobId,
     dep_node: Option<DepNode>,
 ) -> (Q::Value, Option<DepNodeIndex>)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     // Use `JobOwner` so the query will be poisoned if executing it panics.
     let job_owner = JobOwner { state, key };
@@ -484,15 +480,14 @@ fn execute_job<Q, Qcx, const INCR: bool>(
 
 // Fast path for when incr. comp. is off.
 #[inline(always)]
-fn execute_job_non_incr<Q, Qcx>(
+fn execute_job_non_incr<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     key: Q::Key,
     job_id: QueryJobId,
 ) -> (Q::Value, DepNodeIndex)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
 
@@ -521,17 +516,16 @@ fn execute_job_non_incr<Q, Qcx>(
 }
 
 #[inline(always)]
-fn execute_job_incr<Q, Qcx>(
+fn execute_job_incr<Q>(
     query: Q,
-    qcx: Qcx,
-    dep_graph_data: &DepGraphData<Qcx::Deps>,
+    qcx: Q::Qcx,
+    dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
     key: Q::Key,
     mut dep_node_opt: Option<DepNode>,
     job_id: QueryJobId,
 ) -> (Q::Value, DepNodeIndex)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     if !query.anon() && !query.eval_always() {
         // `to_dep_node` is expensive for some `DepKind`s.
@@ -577,16 +571,15 @@ fn execute_job_incr<Q, Qcx>(
 }
 
 #[inline(always)]
-fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
+fn try_load_from_disk_and_cache_in_memory<Q>(
     query: Q,
-    dep_graph_data: &DepGraphData<Qcx::Deps>,
-    qcx: Qcx,
+    dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
+    qcx: Q::Qcx,
     key: &Q::Key,
     dep_node: &DepNode,
 ) -> Option<(Q::Value, DepNodeIndex)>
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     // Note this function can be called concurrently from the same query
     // We must ensure that this is handled correctly.
@@ -764,15 +757,14 @@ fn incremental_verify_ich_failed<Tcx>(
 ///
 /// Note: The optimization is only available during incr. comp.
 #[inline(never)]
-fn ensure_must_run<Q, Qcx>(
+fn ensure_must_run<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     key: &Q::Key,
     check_cache: bool,
 ) -> (bool, Option<DepNode>)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     if query.eval_always() {
         return (true, None);
@@ -817,27 +809,25 @@ pub enum QueryMode {
 }
 
 #[inline(always)]
-pub fn get_query_non_incr<Q, Qcx>(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value
+pub fn get_query_non_incr<Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
 
-    ensure_sufficient_stack(|| try_execute_query::<Q, Qcx, false>(query, qcx, span, key, None).0)
+    ensure_sufficient_stack(|| try_execute_query::<Q, false>(query, qcx, span, key, None).0)
 }
 
 #[inline(always)]
-pub fn get_query_incr<Q, Qcx>(
+pub fn get_query_incr<Q>(
     query: Q,
-    qcx: Qcx,
+    qcx: Q::Qcx,
     span: Span,
     key: Q::Key,
     mode: QueryMode,
 ) -> Option<Q::Value>
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
 
@@ -851,19 +841,17 @@ pub fn get_query_incr<Q, Qcx>(
         None
     };
 
-    let (result, dep_node_index) = ensure_sufficient_stack(|| {
-        try_execute_query::<_, _, true>(query, qcx, span, key, dep_node)
-    });
+    let (result, dep_node_index) =
+        ensure_sufficient_stack(|| try_execute_query::<Q, true>(query, qcx, span, key, dep_node));
     if let Some(dep_node_index) = dep_node_index {
         qcx.dep_context().dep_graph().read_index(dep_node_index)
     }
     Some(result)
 }
 
-pub fn force_query<Q, Qcx>(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode)
+pub fn force_query<Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode)
 where
-    Q: QueryDispatcher<Qcx>,
-    Qcx: QueryContext,
+    Q: QueryDispatcher,
 {
     // We may be concurrently trying both execute and force a query.
     // Ensure that only one of them runs the query.
@@ -875,6 +863,6 @@ pub fn force_query<Q, Qcx>(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode)
     debug_assert!(!query.anon());
 
     ensure_sufficient_stack(|| {
-        try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
+        try_execute_query::<Q, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
     });
 }