Repository: rust-lang/rust
File: compiler/rustc_query_impl/src/plumbing.rs (Rust)

Code before:
                            ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) &&
                                $crate::plumbing::loadable_from_disk(tcx, index)
                        })
                    } {
                        None
                    }),
                    value_from_cycle_error: |tcx, cycle, guar| {
                        let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
                        erase::erase_val(result)
                    },
                    hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
                    format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
                    description_fn: $crate::queries::_description_fns::$name,
                }
            }

            const FLAGS: QueryFlags = QueryFlags {
                is_anon: is_anon!([$($modifiers)*]),
                is_depth_limit: depth_limit!([$($modifiers)*]),
                is_feedable: feedable!([$($modifiers)*]),
            };

            /// Marker type that implements [`QueryVTableGetter`] for this query.
            pub(crate) enum VTableGetter {}

            impl<'tcx> QueryVTableGetter<'tcx, FLAGS> for VTableGetter {
                type Cache = queries::$name::Storage<'tcx>;

                const NAME: &'static &'static str = &stringify!($name);

                #[inline(always)]
                fn query_dispatcher(tcx: TyCtxt<'tcx>)
                    -> SemiDynamicQueryDispatcher<'tcx, Self::Cache, FLAGS>
                {
                    SemiDynamicQueryDispatcher {
                        vtable: &tcx.query_system.query_vtables.$name,
                    }
                }
            }

            /// Internal per-query plumbing for collecting the set of active jobs for this query.
            ///
            /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`.
            pub(crate) fn gather_active_jobs<'tcx>(
                tcx: TyCtxt<'tcx>,
                require_complete: bool,
                job_map_out: &mut QueryJobMap<'tcx>,
            ) -> Option<()> {
                let make_frame = |tcx: TyCtxt<'tcx>, key| {
                    let vtable = &tcx.query_system.query_vtables.$name;
                    $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key)

Review comment (refactor):
This is a trait with a single implementer (per query).
Would it be hard to refactor it into a free (per query) function somehow?
(Similarly to how `restore_val` was removed from the trait's interface.)

Code after:

            impl<'tcx> GetQueryVTable<'tcx> for VTableGetter {
                type Cache = rustc_middle::queries::$name::Storage<'tcx>;

                #[inline(always)]
                fn query_vtable(tcx: TyCtxt<'tcx>) -> &'tcx QueryVTable<'tcx, Self::Cache> {
                    &tcx.query_system.query_vtables.$name
                }
            }

            /// Internal per-query plumbing for collecting the set of active jobs for this query.
            ///
            /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`.
            pub(crate) fn gather_active_jobs<'tcx>(
                tcx: TyCtxt<'tcx>,
                require_complete: bool,
                job_map_out: &mut QueryJobMap<'tcx>,
            ) -> Option<()> {
                let make_frame = |tcx: TyCtxt<'tcx>, key| {
                    let vtable = &tcx.query_system.query_vtables.$name;
                    $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key)
                };

                // Call `gather_active_jobs_inner` to do the actual work.
                let res = crate::execution::gather_active_jobs_inner(&tcx.query_system.states.$name,
                    tcx,
                    make_frame,
                    require_complete,
                    job_map_out,
                );

                // this can be called during unwinding, and the function has a `try_`-prefix, so
                // don't `unwrap()` here, just manually check for `None` and do best-effort error
                // reporting.
                if res.is_none() {
                    tracing::warn!(
                        "Failed to collect active jobs for query with name `{}`!",
                        stringify!($name)
                    );
                }
                res
            }

            pub(crate) fn alloc_self_profile_query_strings<'tcx>(
                tcx: TyCtxt<'tcx>,
                string_cache: &mut QueryKeyStringCache
            ) {
                $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
                    tcx,
                    stringify!($name),
                    &tcx.query_system.caches.$name,