diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 95995b956cda5..c00d8826f00cd 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2483,6 +2483,12 @@ rustc_queries! { cache_on_disk_if { true } } + // UwU + query check_instance_wf(key: ty::Instance<'tcx>) { + desc { "monomorphization-time checking of where-clauses" } + cache_on_disk_if { true } + } + /// Builds the set of functions that should be skipped for the move-size check. query skip_move_check_fns(_: ()) -> &'tcx FxIndexSet { arena_cache diff --git a/compiler/rustc_monomorphize/src/mono_checks/mod.rs b/compiler/rustc_monomorphize/src/mono_checks/mod.rs index 1ecda824fb8c2..15174fa7bb965 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/mod.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/mod.rs @@ -12,6 +12,7 @@ fn check_mono_item<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { let body = tcx.instance_mir(instance.def); abi_check::check_feature_dependent_abi(tcx, instance, body); move_check::check_moves(tcx, instance, body); + tcx.ensure().check_instance_wf(instance); } pub(super) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_traits/src/check_instance_wf.rs b/compiler/rustc_traits/src/check_instance_wf.rs new file mode 100644 index 0000000000000..6d7e5fccca348 --- /dev/null +++ b/compiler/rustc_traits/src/check_instance_wf.rs @@ -0,0 +1,28 @@ +use rustc_infer::infer::TyCtxtInferExt as _; +use rustc_middle::ty::{self, TyCtxt, TypingEnv}; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; + +pub(crate) fn check_instance_wf<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) { + let ty::InstanceKind::Item(def_id) = instance.def else { + // Probably want other instances too...: + return; + }; + + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(TypingEnv::fully_monomorphized()); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + + ocx.register_obligations( + tcx.predicates_of(def_id).instantiate(tcx, instance.args).into_iter().map( + |(clause, span)| { + Obligation::new(tcx, ObligationCause::dummy_with_span(span), param_env, clause) + }, + ), + ); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(errors); + } +} diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index d2f979bd6d9dc..b7b47b41f6be5 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -5,6 +5,7 @@ #![warn(unreachable_pub)] // tidy-alphabetical-end +mod check_instance_wf; mod codegen; mod dropck_outlives; mod evaluate_obligation; @@ -25,4 +26,5 @@ pub fn provide(p: &mut Providers) { normalize_erasing_regions::provide(p); type_op::provide(p); p.codegen_select_candidate = codegen::codegen_select_candidate; + p.check_instance_wf = check_instance_wf::check_instance_wf; }