Skip to content

Add a way to decouple the implementation and the declaration of a TyCtxt method. #116052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 23, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::hooks;
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
use rustc_session::Session;
use rustc_span::Symbol;
Expand Down Expand Up @@ -127,7 +128,7 @@ impl CodegenBackend for GccCodegenBackend {
*self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None);
}

fn provide(&self, providers: &mut Providers) {
fn provide(&self, providers: &mut Providers, _: &mut hooks::Providers) {
// FIXME(antoyo) compute list of enabled features from cli flags
providers.global_backend_features = |_tcx, ()| vec![];
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, Subd
use rustc_fluent_macro::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::hooks;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
Expand Down Expand Up @@ -268,7 +269,7 @@ impl CodegenBackend for LlvmCodegenBackend {
llvm_util::init(sess); // Make sure llvm is inited
}

fn provide(&self, providers: &mut Providers) {
fn provide(&self, providers: &mut Providers, _hooks: &mut hooks::Providers) {
providers.global_backend_features =
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::ErrorGuaranteed;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::hooks;
use rustc_middle::query::{ExternProviders, Providers};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Ty, TyCtxt};
Expand Down Expand Up @@ -84,7 +85,7 @@ pub trait CodegenBackend {
Box::new(crate::back::metadata::DefaultMetadataLoader)
}

fn provide(&self, _providers: &mut Providers) {}
fn provide(&self, _providers: &mut Providers, _hooks: &mut hooks::Providers) {}
fn provide_extern(&self, _providers: &mut ExternProviders) {}
fn codegen_crate<'tcx>(
&self,
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::errors::MaxNumNodesInConstErr;
use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar};
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};

Expand Down Expand Up @@ -86,17 +87,17 @@ pub(crate) fn eval_to_valtree<'tcx>(

#[instrument(skip(tcx), level = "debug")]
pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
tcx: TyCtxt<'tcx>,
tcx: TyCtxtAt<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<mir::DestructuredConstant<'tcx>> {
let param_env = ty::ParamEnv::reveal_all();
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
let ecx = mk_eval_cx(tcx.tcx, tcx.span, param_env, CanAccessStatics::No);
let op = ecx.const_val_to_op(val, ty, None).ok()?;

// We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match ty.kind() {
ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op),
ty::Array(_, len) => (len.eval_target_usize(tcx.tcx, param_env) as usize, None, op),
ty::Adt(def, _) if def.variants().is_empty() => {
return None;
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ pub use errors::ReportErrorExt;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_middle::query::Providers;
use rustc_middle::ty;
use rustc_middle::{hooks, ty};

fluent_messages! { "../messages.ftl" }

pub fn provide(providers: &mut Providers) {
pub fn provide(providers: &mut Providers, hooks: &mut hooks::Providers) {
const_eval::provide(providers);
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
Expand All @@ -52,8 +52,8 @@ pub fn provide(providers: &mut Providers) {
let (param_env, raw) = param_env_and_value.into_parts();
const_eval::eval_to_valtree(tcx, param_env, raw)
};
providers.try_destructure_mir_constant_for_diagnostics =
|tcx, (cv, ty)| const_eval::try_destructure_mir_constant_for_diagnostics(tcx, cv, ty);
hooks.try_destructure_mir_constant_for_diagnostics =
const_eval::try_destructure_mir_constant_for_diagnostics;
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
};
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::hooks;
use rustc_middle::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_mir_build as mir_build;
Expand Down Expand Up @@ -645,15 +646,16 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
outputs.into()
}

pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
pub static DEFAULT_QUERY_PROVIDERS: LazyLock<(Providers, hooks::Providers)> = LazyLock::new(|| {
let providers = &mut Providers::default();
let hooks = &mut hooks::Providers::default();
providers.analysis = analysis;
providers.hir_crate = rustc_ast_lowering::lower_to_hir;
providers.output_filenames = output_filenames;
providers.resolver_for_lowering = resolver_for_lowering;
providers.early_lint_checks = early_lint_checks;
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_const_eval::provide(providers, hooks);
rustc_middle::hir::provide(providers);
mir_borrowck::provide(providers);
mir_build::provide(providers);
Expand All @@ -672,7 +674,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
rustc_lint::provide(providers);
rustc_symbol_mangling::provide(providers);
rustc_codegen_ssa::provide(providers);
*providers
(*providers, *hooks)
});

pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock::new(|| {
Expand Down Expand Up @@ -702,8 +704,8 @@ pub fn create_global_ctxt<'tcx>(
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);

let codegen_backend = compiler.codegen_backend();
let mut local_providers = *DEFAULT_QUERY_PROVIDERS;
codegen_backend.provide(&mut local_providers);
let (mut local_providers, mut hooks) = *DEFAULT_QUERY_PROVIDERS;
codegen_backend.provide(&mut local_providers, &mut hooks);

let mut extern_providers = *DEFAULT_EXTERN_QUERY_PROVIDERS;
codegen_backend.provide_extern(&mut extern_providers);
Expand Down Expand Up @@ -732,6 +734,7 @@ pub fn create_global_ctxt<'tcx>(
query_result_on_disk_cache,
incremental,
),
hooks,
)
})
})
Expand Down
65 changes: 65 additions & 0 deletions compiler/rustc_middle/src/hooks/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::mir;
use crate::query::TyCtxtAt;
use crate::ty::{Ty, TyCtxt};
use rustc_span::DUMMY_SP;

macro_rules! declare_hooks {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to have some docs in this file that explain hat a "hook" is and how it differs from a "query".

($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => {

impl<'tcx> TyCtxt<'tcx> {
$(
$(#[$attr])*
#[inline(always)]
#[must_use]
pub fn $name(self, $($arg: $K,)*) -> $V
{
self.at(DUMMY_SP).$name($($arg,)*)
}
)*
}

impl<'tcx> TyCtxtAt<'tcx> {
$(
$(#[$attr])*
#[inline(always)]
#[must_use]
#[instrument(level = "debug", skip(self), ret)]
pub fn $name(self, $($arg: $K,)*) -> $V
{
(self.tcx.hooks.$name)(self, $($arg,)*)
}
)*
}

pub struct Providers {
$(pub $name: for<'tcx> fn(
TyCtxtAt<'tcx>,
$($arg: $K,)*
) -> $V,)*
}

impl Default for Providers {
fn default() -> Self {
Providers {
$($name: |_, $($arg,)*| bug!(
"`tcx.{}{:?}` cannot be called as `{}` was never assigned to a provider function.\n",
stringify!($name),
($($arg,)*),
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_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ mod macros;
pub mod arena;
pub mod error;
pub mod hir;
pub mod hooks;
pub mod infer;
pub mod lint;
pub mod metadata;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1691,7 +1691,7 @@ fn pretty_print_const_value_tcx<'tcx>(
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
let ct = tcx.lift(ct).unwrap();
let ty = tcx.lift(ty).unwrap();
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics(ct, ty) {
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
match *ty.kind() {
ty::Array(..) => {
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,16 +1100,6 @@ rustc_queries! {
desc { "destructuring type level constant"}
}

/// 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.
query try_destructure_mir_constant_for_diagnostics(
key: (mir::ConstValue<'tcx>, Ty<'tcx>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So can we now remove the faulty StableHash implementation(s) that were previously needed to make this work as a query?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What "faulty StableHash implementationt(s)" are you thinking about?

Copy link
Member

@RalfJung RalfJung Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quoting things @oli-obk said (potentially quoting them incorrectly), I don't actually understand the underlying issue here. Also see Zulip.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the zulip, still don't get it 👍🏻

Also the "hash eq implies eq" is very scary...

) -> Option<mir::DestructuredConstant<'tcx>> {
desc { "destructuring MIR constant"}
no_hash
eval_always
}

query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> mir::ConstValue<'tcx> {
desc { "getting a &core::panic::Location referring to a span" }
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@ pub struct GlobalCtxt<'tcx> {
/// Common consts, pre-interned for your convenience.
pub consts: CommonConsts<'tcx>,

/// Hooks to be able to register functions in other crates that can then still
/// be called from rustc_middle.
pub(crate) hooks: crate::hooks::Providers,

untracked: Untracked,

pub query_system: QuerySystem<'tcx>,
Expand Down Expand Up @@ -703,6 +707,7 @@ impl<'tcx> TyCtxt<'tcx> {
dep_graph: DepGraph,
query_kinds: &'tcx [DepKindStruct<'tcx>],
query_system: QuerySystem<'tcx>,
hooks: crate::hooks::Providers,
) -> GlobalCtxt<'tcx> {
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err);
Expand All @@ -721,6 +726,7 @@ impl<'tcx> TyCtxt<'tcx> {
hir_arena,
interners,
dep_graph,
hooks,
prof: s.prof.clone(),
types: common_types,
lifetimes: common_lifetimes,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ pub(crate) fn create_config(
let body = hir.body(hir.body_owned_by(def_id));
debug!("visiting body for {def_id:?}");
EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
(rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
(rustc_interface::DEFAULT_QUERY_PROVIDERS.0.typeck)(tcx, def_id)
};
}),
make_codegen_backend: None,
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ fn field_of_struct<'tcx>(
field: &Ident,
) -> Option<mir::Const<'tcx>> {
if let mir::Const::Val(result, ty) = result
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty))
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics(result, ty)
&& let Some(dc_variant) = dc.variant
&& let Some(variant) = adt_def.variants().get(dc_variant)
&& let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
Expand Down