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

Code before:
        }),
        try_load_from_on_disk_cache: Some(|tcx, dep_node| {
            try_load_from_on_disk_cache_inner(Q::query_vtable(tcx), tcx, dep_node)
        }),
    }
}

macro_rules! define_vtables {
    (
        queries {
            $(
                $(#[$attr:meta])*
                [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,
            )*
        }
        non_queries {
            $(
                $(#[$nq_attr:meta])*
                $nq_name:ident,
            )*
        }
    ) => {
        // Create an array of vtables, one for each dep kind (non-query and query).
        pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>)
            -> &'tcx [DepKindVTable<'tcx>]
        {
            // The small number of non-query vtables: `Null`, `Red`, etc.
            let nq_vtables = [
                $(
                    non_query::$nq_name(),
                )*
            ];

            // The large number of query vtables.
            let q_vtables: [DepKindVTable<'tcx>; _] = [
                $(
                    $crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
                        $crate::query_impl::$name::VTableGetter,
                    >(
                        is_anon!([$($modifiers)*]),
                        is_eval_always!([$($modifiers)*]),
                    )
                ),*
            ];

            // Non-query vtables must come before query vtables, to match the order of `DepKind`.
            let iter = nq_vtables.into_iter().chain(q_vtables.into_iter());
            arena.alloc_from_iter(iter)
        }
    }
}

Review comment (suggestion):
I'd really like to keep this function definition in normal code, and have `rustc_middle::rustc_with_all_queries! { define_vtables! }` expand to a pair of arrays inside that function.

That way, the function signature and the arena-allocation stuff get to be ordinary Rust code, so IDE features work normally without any special effort.

Code after:
}

macro_rules! define_dep_kind_vtables {
    (
        queries {
            $(
                $(#[$attr:meta])*
                [$($modifiers:tt)*]
                fn $name:ident($K:ty) -> $V:ty,
            )*
        }
        non_queries {
            $(
                $(#[$nq_attr:meta])*
                $nq_name:ident,
            )*
        }
    ) => {{
        // The small number of non-query vtables: `Null`, `Red`, etc.
        let nq_vtables = [
            $(
                non_query::$nq_name(),
            )*
        ];

        // The large number of query vtables.
        let q_vtables: [DepKindVTable<'tcx>; _] = [
            $(
                $crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
                    $crate::query_impl::$name::VTableGetter,
                >(
                    is_anon!([$($modifiers)*]),
                    if_cache_on_disk!([$($modifiers)*] true false),
                    is_eval_always!([$($modifiers)*]),
                )
            ),*
        ];

        (nq_vtables, q_vtables)
    }}
}

// Create an array of vtables, one for each dep kind (non-query and query).
pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
    let (nq_vtables, q_vtables) =
        rustc_middle::rustc_with_all_queries! { define_dep_kind_vtables! };

    // Non-query vtables must come before query vtables, to match the order of `DepKind`.
    arena.alloc_from_iter(nq_vtables.into_iter().chain(q_vtables.into_iter()))
}