| //! "Hooks" let you write `tcx` methods in downstream crates and call them in this crate, reducing | |
| //! the amount of code that needs to be in this crate (which is already very big). This is somewhat | |
| //! similar to queries, but queries come with a lot of machinery for caching and incremental | |
| //! compilation, whereas hooks are just plain function pointers without any of the query magic. | |
| use rustc_hir::def_id::{DefId, DefPathHash}; | |
| use rustc_session::StableCrateId; | |
| use rustc_span::def_id::{CrateNum, LocalDefId}; | |
| use rustc_span::{ExpnHash, ExpnId}; | |
| use crate::mir; | |
| use crate::query::on_disk_cache::CacheEncoder; | |
| use crate::ty::{Ty, TyCtxt}; | |
| macro_rules! declare_hooks { | |
| ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => { | |
| impl<'tcx> TyCtxt<'tcx> { | |
| $( | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name(self, $($arg: $K,)*) -> $V | |
| { | |
| (self.hooks.$name)(self, $($arg,)*) | |
| } | |
| )* | |
| } | |
| pub struct Providers { | |
| $(pub $name: for<'tcx> fn( | |
| TyCtxt<'tcx>, | |
| $($arg: $K,)* | |
| ) -> $V,)* | |
| } | |
| impl Default for Providers { | |
| fn default() -> Self { | |
| #[allow(unused)] | |
| Providers { | |
| $($name: | |
| |_, $($arg,)*| default_hook(stringify!($name))),* | |
| } | |
| } | |
| } | |
| impl Copy for Providers {} | |
| impl Clone for Providers { | |
| fn clone(&self) -> Self { *self } | |
| } | |
| }; | |
| } | |
| declare_hooks! { | |
| /// Tries to destructure an `mir::Const` ADT or array into its variant index | |
| /// and its field values. This should only be used for pretty printing. | |
| hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>; | |
| /// Getting a &core::panic::Location referring to a span. | |
| hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue; | |
| /// Returns `true` if this def is a function-like thing that is eligible for | |
| /// coverage instrumentation under `-Cinstrument-coverage`. | |
| /// | |
| /// (Eligible functions might nevertheless be skipped for other reasons.) | |
| hook is_eligible_for_coverage(key: LocalDefId) -> bool; | |
| /// Imports all `SourceFile`s from the given crate into the current session. | |
| /// This normally happens automatically when we decode a `Span` from | |
| /// that crate's metadata - however, the incr comp cache needs | |
| /// to trigger this manually when decoding a foreign `Span` | |
| hook import_source_files(key: CrateNum) -> (); | |
| hook expn_hash_to_expn_id( | |
| cnum: CrateNum, | |
| index_guess: u32, | |
| hash: ExpnHash | |
| ) -> ExpnId; | |
| /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation | |
| /// session, if it still exists. This is used during incremental compilation to | |
| /// turn a deserialized `DefPathHash` into its current `DefId`. | |
| /// Will fetch a DefId from a DefPathHash for a foreign crate. | |
| hook def_path_hash_to_def_id_extern(hash: DefPathHash, stable_crate_id: StableCrateId) -> Option<DefId>; | |
| /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we | |
| /// can just link to the upstream crate and therefore don't need a mono item. | |
| /// | |
| /// Note: this hook isn't called within `rustc_middle` but #127779 suggests it's a hook instead | |
| /// of a normal function because external tools might want to override it. | |
| hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool; | |
| hook alloc_self_profile_query_strings() -> (); | |
| /// Saves and writes the DepGraph to the file system. | |
| /// | |
| /// This function saves both the dep-graph and the query result cache, | |
| /// and drops the result cache. | |
| /// | |
| /// This function should only run after all queries have completed. | |
| /// Trying to execute a query afterwards would attempt to read the result cache we just dropped. | |
| hook save_dep_graph() -> (); | |
| hook verify_query_key_hashes() -> (); | |
| /// Ensure the given scalar is valid for the given type. | |
| /// This checks non-recursive runtime validity. | |
| hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool; | |
| /// **Do not call this directly; call the `mir_built` query instead.** | |
| /// | |
| /// Creates the MIR for a given `DefId`, including unreachable code. | |
| hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>; | |
| /// Serializes all eligible query return values into the on-disk cache. | |
| hook encode_query_values(encoder: &mut CacheEncoder<'_, 'tcx>) -> (); | |
| } | |
| #[cold] | |
| fn default_hook(name: &str) -> ! { | |
| bug!("`tcx.{name}` cannot be called as `{name}` was never assigned to a provider function") | |
| } |