From 1e370fffd2e179a2610021e1f8880e54a0973970 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:19:00 +0100 Subject: [PATCH 01/14] Implements funtionality of type_id_implements_trait and its ilk --- .../src/const_eval/machine.rs | 54 +++++++++++++++++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 14 +++++ compiler/rustc_span/src/symbol.rs | 2 + library/core/src/intrinsics/mod.rs | 18 +++++++ library/core/src/mem/type_info.rs | 27 +++++++++- 5 files changed, 111 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 719187b990122..7700474d1687b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,16 +5,19 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::{Pointer, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement}; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::{bug, mir}; +use rustc_middle::ty::{self, PolyExistentialPredicate, Ty, TyCtxt}; +use rustc_middle::{bug, mir, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::FnAbi; +use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; use super::error::*; @@ -586,6 +589,51 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } } + sym::type_id_is_trait => { + let kind = ecx.read_type_id(&args[0])?.kind(); + let is_trait = matches!(kind, ty::Dynamic(..)); + ecx.write_scalar(Scalar::from_bool(is_trait), dest)?; + } + + sym::type_id_implements_trait => { + let type_from_type_id = ecx.read_type_id(&args[0])?; + let trait_from_type_id = ecx.read_type_id(&args[1])?; + + // TODO: Not quite sure how best to get this into scope... I'm not actually sure what it is meant to do. Please inform me. + // ensure_monomorphic_enough(tcx, result_ty)?; + + let ty::Dynamic(predicates, _) = trait_from_type_id.kind() else { + span_bug!( + ecx.find_closest_untracked_caller_location(), + "Invalid type provided to type_id_implements_trait. The second parameter must represent a dyn Trait, instead you gave us {trait_from_type_id}." + ); + }; + + let (infcx, param_env) = + ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env()); + + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(predicates.iter().map( + |predicate: PolyExistentialPredicate<'_>| { + let predicate = predicate.with_self_ty(ecx.tcx.tcx, type_from_type_id); + // Lifetimes can only be 'static because of the bound on T + let predicate = ty::fold_regions(ecx.tcx.tcx, predicate, |r, _| { + if r == ecx.tcx.tcx.lifetimes.re_erased { + ecx.tcx.tcx.lifetimes.re_static + } else { + r + } + }); + Obligation::new(ecx.tcx.tcx, ObligationCause::dummy(), param_env, predicate) + }, + )); + let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty(); + // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" + let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); + + ecx.write_scalar(Scalar::from_bool(type_impls_trait && regions_are_valid), dest)?; + } + sym::type_of => { let ty = ecx.read_type_id(&args[0])?; ecx.write_type_info(ty, dest)?; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 22ee490b81a7b..3533ca038b827 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -213,6 +213,8 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::truncf128 | sym::type_id | sym::type_id_eq + | sym::type_id_implements_trait + | sym::type_id_is_trait | sym::type_name | sym::type_of | sym::ub_checks @@ -322,6 +324,18 @@ pub(crate) fn check_intrinsic_type( let type_id = tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(); (0, 0, vec![type_id, type_id], tcx.types.bool) } + sym::type_id_implements_trait => ( + 0, + 0, + vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(); 2], + tcx.types.bool, + ), + sym::type_id_is_trait => ( + 0, + 0, + vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap()], + tcx.types.bool, + ), sym::type_of => ( 0, 0, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b80d624bc4966..e65731b5dd472 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2339,6 +2339,8 @@ symbols! { type_const, type_id, type_id_eq, + type_id_implements_trait, + type_id_is_trait, type_info, type_ir, type_ir_infer_ctxt_like, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 051dda731881f..628190889394c 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2852,6 +2852,24 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; #[rustc_intrinsic_const_stable_indirect] pub const unsafe fn align_of_val(ptr: *const T) -> usize; +/// Check if a type represented by a `TypeId` is a dyn Trait. +/// It can only be called at compile time, the backends do +/// not implement it. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +pub const fn type_id_is_trait(_trait: crate::any::TypeId) -> bool { + panic!("`TypeId::implements_trait_represented_by_type_id` can only be called at compile-time") +} + +/// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. +/// It can only be called at compile time, the backends do +/// not implement it. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +pub const fn type_id_implements_trait(_id: crate::any::TypeId, _trait: crate::any::TypeId) -> bool { + panic!("`TypeId::implements_trait` can only be called at compile-time") +} + /// Compute the type information of a concrete type. /// It can only be called at compile time, the backends do /// not implement it. diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b30803c97c98..5fe0f8eb8659f 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -2,7 +2,8 @@ //! runtime or const-eval processable way. use crate::any::TypeId; -use crate::intrinsics::type_of; +use crate::intrinsics::{type_id_implements_trait, type_id_is_trait, type_of}; +use crate::ptr; /// Compile-time type information. #[derive(Debug)] @@ -24,6 +25,30 @@ impl TypeId { pub const fn info(self) -> Type { type_of(self) } + + /// Checks if the type represented by the `TypeId` implements the trait. + /// It can only be called at compile time. + pub const fn implements_trait< + T: ptr::Pointee> + ?Sized + 'static, + >( + self, + ) -> bool { + type_id_implements_trait(self, TypeId::of::()) + } + + /// Checks if the type represented by the `TypeId` implements the trait represented by the secondary `TypeId`. + /// Returns `None` if the `trait_represented_by_type_id` is not a trait represented by type id. + /// It can only be called at compile time. + pub const fn implements_trait_represented_by_type_id( + self, + trait_represented_by_type_id: Self, + ) -> Option { + if type_id_is_trait(trait_represented_by_type_id) { + Some(type_id_implements_trait(self, trait_represented_by_type_id)) + } else { + None + } + } } impl Type { From 25f8a983db3d546675acc3b25bdbe9488e4df26a Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:19:09 +0100 Subject: [PATCH 02/14] De-duplicate! --- .../src/const_eval/machine.rs | 38 ++++--------------- .../src/interpret/intrinsics.rs | 25 ++---------- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/util.rs | 37 +++++++++++++++++- 4 files changed, 46 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7700474d1687b..49ab9d75253d6 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,24 +5,22 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; -use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::{Pointer, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement}; -use rustc_middle::ty::{self, PolyExistentialPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::FnAbi; -use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; +use crate::interpret::util::{ensure_monomorphic_enough, type_implements_predicates}; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, @@ -599,9 +597,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let type_from_type_id = ecx.read_type_id(&args[0])?; let trait_from_type_id = ecx.read_type_id(&args[1])?; - // TODO: Not quite sure how best to get this into scope... I'm not actually sure what it is meant to do. Please inform me. - // ensure_monomorphic_enough(tcx, result_ty)?; - + ensure_monomorphic_enough(ecx.tcx.tcx, trait_from_type_id)?; let ty::Dynamic(predicates, _) = trait_from_type_id.kind() else { span_bug!( ecx.find_closest_untracked_caller_location(), @@ -609,29 +605,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ); }; - let (infcx, param_env) = - ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env()); - - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(predicates.iter().map( - |predicate: PolyExistentialPredicate<'_>| { - let predicate = predicate.with_self_ty(ecx.tcx.tcx, type_from_type_id); - // Lifetimes can only be 'static because of the bound on T - let predicate = ty::fold_regions(ecx.tcx.tcx, predicate, |r, _| { - if r == ecx.tcx.tcx.lifetimes.re_erased { - ecx.tcx.tcx.lifetimes.re_static - } else { - r - } - }); - Obligation::new(ecx.tcx.tcx, ObligationCause::dummy(), param_env, predicate) - }, - )); - let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty(); - // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" - let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); - - ecx.write_scalar(Scalar::from_bool(type_impls_trait && regions_are_valid), dest)?; + let implements = type_implements_predicates(ecx, type_from_type_id, predicates)?; + + ecx.write_scalar(Scalar::from_bool(implements), dest)?; } sym::type_of => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e526f6120689a..4eb9e3a31e97a 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,15 +7,12 @@ mod simd; use rustc_abi::{FIRST_VARIANT, FieldIdx, HasDataLayout, Size, VariantIdx}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_data_structures::assert_matches; -use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint}; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{FloatTy, Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; use rustc_span::{Symbol, sym}; -use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; use tracing::trace; use super::memory::MemoryKind; @@ -27,6 +24,7 @@ use super::{ }; use crate::fluent_generated as fluent; use crate::interpret::Writeable; +use crate::interpret::util::type_implements_predicates; #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum MulAddType { @@ -226,7 +224,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let tp_ty = instance.args.type_at(0); let result_ty = instance.args.type_at(1); - ensure_monomorphic_enough(tcx, tp_ty)?; ensure_monomorphic_enough(tcx, result_ty)?; let ty::Dynamic(preds, _) = result_ty.kind() else { span_bug!( @@ -235,23 +232,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); }; - let (infcx, param_env) = - self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); - - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| { - let pred = pred.with_self_ty(tcx, tp_ty); - // Lifetimes can only be 'static because of the bound on T - let pred = ty::fold_regions(tcx, pred, |r, _| { - if r == tcx.lifetimes.re_erased { tcx.lifetimes.re_static } else { r } - }); - Obligation::new(tcx, ObligationCause::dummy(), param_env, pred) - })); - let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty(); - // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" - let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); - - if regions_are_valid && type_impls_trait { + if type_implements_predicates(self, tp_ty, preds)? { let vtable_ptr = self.get_vtable_ptr(tp_ty, preds)?; // Writing a non-null pointer into an `Option` will automatically make it `Some`. self.write_pointer(vtable_ptr, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 2f365ec77b33e..b3f7ec6d359a0 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -15,7 +15,7 @@ mod projection; mod stack; mod step; mod traits; -mod util; +pub mod util; mod validity; mod visitor; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 1e18a22be81c2..deba6ba4c3419 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,12 +1,45 @@ -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; +use rustc_infer::infer::TyCtxtInferExt; +#[allow(rustc::direct_use_of_rustc_type_ir)] +use rustc_infer::infer::canonical::ir::Interner; +use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::mir; use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{PolyExistentialPredicate, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; use super::{InterpCx, MPlaceTy, MemoryKind, interp_ok, throw_inval}; use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult}; +use crate::interpret::Machine; + +/// Checks if a type implements predicates. +/// Calls `ensure_monomorphic_enough` on `ty` for you. +pub(crate) fn type_implements_predicates<'tcx, M: Machine<'tcx>>( + ecx: &mut InterpCx<'tcx, M>, + ty: Ty<'tcx>, + preds: as Interner>::BoundExistentialPredicates, +) -> InterpResult<'tcx, bool> { + ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; + + let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env); + + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| { + let pred = pred.with_self_ty(ecx.tcx.tcx, ty); + // Lifetimes can only be 'static because of the bound on T + let pred = rustc_middle::ty::fold_regions(ecx.tcx.tcx, pred, |r, _| { + if r == ecx.tcx.tcx.lifetimes.re_erased { ecx.tcx.tcx.lifetimes.re_static } else { r } + }); + Obligation::new(ecx.tcx.tcx, ObligationCause::dummy(), param_env, pred) + })); + let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty(); + // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" + let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); + + interp_ok(regions_are_valid && type_impls_trait) +} /// Checks whether a type contains generic parameters which must be instantiated. /// From 33134d9cc66d2df0ee08429efae32bee5d7e51aa Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:19:19 +0100 Subject: [PATCH 03/14] Add test. --- library/backtrace | 2 +- library/coretests/tests/mem/type_info.rs | 13 +++++++++++++ src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/llvm-project | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/library/backtrace b/library/backtrace index 28ec93b503bf0..b65ab935fb2e0 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit 28ec93b503bf0410745bc3d571bf3dc1caac3019 +Subproject commit b65ab935fb2e0d59dba8966ffca09c9cc5a5f57c diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 87f2d5dd8289c..4cfc74c085209 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -292,3 +292,16 @@ fn test_dynamic_traits() { assert!(sync.trait_ty.is_auto); } } + +#[test] +fn test_implements_trait() { + struct Garlic; + trait Blah {} + impl Blah for Garlic {} + + const { + assert!(TypeId::of::().implements_trait::()); + assert!(TypeId::of::().implements_trait::()); + assert!(!TypeId::of::<*const Box>().implements_trait::()); + } +} diff --git a/src/doc/reference b/src/doc/reference index 990819b86c22b..28b5a54419985 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 990819b86c22bbf538c0526f0287670f3dc1a67a +Subproject commit 28b5a54419985f03db5294de5eede71b6665b594 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index bac931ef1673a..8de6ff811315a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit bac931ef1673af63fb60c3d691633034713cca20 +Subproject commit 8de6ff811315ac3a96ebe01d74057382e42ffdee diff --git a/src/llvm-project b/src/llvm-project index 41256ab128f2a..00d23d10dc48c 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 41256ab128f2af613b4a16771cda6baa36b55f45 +Subproject commit 00d23d10dc48c6bb9d57ba96d4a748d85d77d0c7 From debe1139d0292fb4d883713dfe81bc3570add980 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:19:26 +0100 Subject: [PATCH 04/14] Fmease fixes. --- compiler/rustc_const_eval/src/interpret/util.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index deba6ba4c3419..d204efe419fa4 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,12 +1,10 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; -#[allow(rustc::direct_use_of_rustc_type_ir)] -use rustc_infer::infer::canonical::ir::Interner; use rustc_infer::traits::{Obligation, ObligationCause}; -use rustc_middle::mir; use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{PolyExistentialPredicate, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_middle::{mir, ty}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; @@ -19,7 +17,7 @@ use crate::interpret::Machine; pub(crate) fn type_implements_predicates<'tcx, M: Machine<'tcx>>( ecx: &mut InterpCx<'tcx, M>, ty: Ty<'tcx>, - preds: as Interner>::BoundExistentialPredicates, + preds: &ty::List>, ) -> InterpResult<'tcx, bool> { ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; From 46b10b5e27ce7c76fd24d5dfb9551fc3152e0f2d Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 07:06:00 +0800 Subject: [PATCH 05/14] Add blocker comment. --- compiler/rustc_const_eval/src/const_eval/machine.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 49ab9d75253d6..4fdfc5ba0aed4 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -587,6 +587,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } } + // TODO: Remove this and replace with reflection. Blocked on reflection supporting dyn traits. sym::type_id_is_trait => { let kind = ecx.read_type_id(&args[0])?.kind(); let is_trait = matches!(kind, ty::Dynamic(..)); From 8d479080ef70ccfe378beadbf5fccb417ff998dd Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 09:26:58 +0800 Subject: [PATCH 06/14] re-export instead of making the util module public --- compiler/rustc_const_eval/src/const_eval/machine.rs | 6 +----- compiler/rustc_const_eval/src/interpret/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4fdfc5ba0aed4..47863eab30a58 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -20,12 +20,8 @@ use tracing::debug; use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; -use crate::interpret::util::{ensure_monomorphic_enough, type_implements_predicates}; use crate::interpret::{ - self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, - compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, - throw_ub_custom, throw_unsup, throw_unsup_format, + self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_predicates }; /// When hitting this many interpreted terminators we emit a deny by default lint diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index b3f7ec6d359a0..554d92e064f23 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -15,7 +15,7 @@ mod projection; mod stack; mod step; mod traits; -pub mod util; +mod util; mod validity; mod visitor; @@ -41,3 +41,4 @@ pub use self::util::EnteredTraceSpan; pub(crate) use self::util::create_static_alloc; pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; +pub(crate) use self::util::{type_implements_predicates, ensure_monomorphic_enough}; From 9e67f0e5001c320465c3a8e34425fcea9be3a6b7 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 09:31:45 +0800 Subject: [PATCH 07/14] rename 'implement' to 'has' --- library/core/src/mem/type_info.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 5fe0f8eb8659f..f2beabdb1f2a6 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -28,7 +28,7 @@ impl TypeId { /// Checks if the type represented by the `TypeId` implements the trait. /// It can only be called at compile time. - pub const fn implements_trait< + pub const fn has_trait< T: ptr::Pointee> + ?Sized + 'static, >( self, @@ -39,7 +39,7 @@ impl TypeId { /// Checks if the type represented by the `TypeId` implements the trait represented by the secondary `TypeId`. /// Returns `None` if the `trait_represented_by_type_id` is not a trait represented by type id. /// It can only be called at compile time. - pub const fn implements_trait_represented_by_type_id( + pub const fn has_trait_represented_by_type_id( self, trait_represented_by_type_id: Self, ) -> Option { From be728c450f31e859cb4dc177a5c286036b336aa7 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 09:32:40 +0800 Subject: [PATCH 08/14] fmt --- compiler/rustc_const_eval/src/const_eval/machine.rs | 6 +++++- compiler/rustc_const_eval/src/interpret/mod.rs | 5 +++-- library/core/src/mem/type_info.rs | 4 +--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 47863eab30a58..d33e08f10bd42 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -21,7 +21,11 @@ use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ - self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_predicates + self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, + GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, + compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, + throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, + type_implements_predicates, }; /// When hitting this many interpreted terminators we emit a deny by default lint diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 554d92e064f23..9dec85defd3cd 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -38,7 +38,8 @@ use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo}; pub use self::util::EnteredTraceSpan; -pub(crate) use self::util::create_static_alloc; +pub(crate) use self::util::{ + create_static_alloc, ensure_monomorphic_enough, type_implements_predicates, +}; pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; -pub(crate) use self::util::{type_implements_predicates, ensure_monomorphic_enough}; diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index f2beabdb1f2a6..e0a091e9692c4 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -28,9 +28,7 @@ impl TypeId { /// Checks if the type represented by the `TypeId` implements the trait. /// It can only be called at compile time. - pub const fn has_trait< - T: ptr::Pointee> + ?Sized + 'static, - >( + pub const fn has_trait> + ?Sized + 'static>( self, ) -> bool { type_id_implements_trait(self, TypeId::of::()) From bd9b84ee22c296a5b2b51332f8fd1684451947aa Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 09:52:55 +0800 Subject: [PATCH 09/14] de-duplicate --- compiler/rustc_const_eval/src/const_eval/machine.rs | 13 ++++++++----- .../rustc_const_eval/src/interpret/intrinsics.rs | 3 +-- compiler/rustc_const_eval/src/interpret/mod.rs | 4 +--- compiler/rustc_const_eval/src/interpret/util.rs | 4 +++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index d33e08f10bd42..c2b1044e03515 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -23,9 +23,8 @@ use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, - compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, - throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, - type_implements_predicates, + compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, + throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_predicates, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -598,7 +597,6 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let type_from_type_id = ecx.read_type_id(&args[0])?; let trait_from_type_id = ecx.read_type_id(&args[1])?; - ensure_monomorphic_enough(ecx.tcx.tcx, trait_from_type_id)?; let ty::Dynamic(predicates, _) = trait_from_type_id.kind() else { span_bug!( ecx.find_closest_untracked_caller_location(), @@ -606,7 +604,12 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ); }; - let implements = type_implements_predicates(ecx, type_from_type_id, predicates)?; + let implements = type_implements_predicates( + ecx, + type_from_type_id, + trait_from_type_id, + predicates, + )?; ecx.write_scalar(Scalar::from_bool(implements), dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 4eb9e3a31e97a..d79c0459790fe 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -224,7 +224,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let tp_ty = instance.args.type_at(0); let result_ty = instance.args.type_at(1); - ensure_monomorphic_enough(tcx, result_ty)?; let ty::Dynamic(preds, _) = result_ty.kind() else { span_bug!( self.find_closest_untracked_caller_location(), @@ -232,7 +231,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); }; - if type_implements_predicates(self, tp_ty, preds)? { + if type_implements_predicates(self, tp_ty, result_ty, preds)? { let vtable_ptr = self.get_vtable_ptr(tp_ty, preds)?; // Writing a non-null pointer into an `Option` will automatically make it `Some`. self.write_pointer(vtable_ptr, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 9dec85defd3cd..5c8ebabe1a1c3 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -38,8 +38,6 @@ use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo}; pub use self::util::EnteredTraceSpan; -pub(crate) use self::util::{ - create_static_alloc, ensure_monomorphic_enough, type_implements_predicates, -}; +pub(crate) use self::util::{create_static_alloc, type_implements_predicates}; pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index d204efe419fa4..85e770d384920 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -13,13 +13,15 @@ use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationR use crate::interpret::Machine; /// Checks if a type implements predicates. -/// Calls `ensure_monomorphic_enough` on `ty` for you. +/// Calls `ensure_monomorphic_enough` on `ty` and `trait_ty` for you. pub(crate) fn type_implements_predicates<'tcx, M: Machine<'tcx>>( ecx: &mut InterpCx<'tcx, M>, ty: Ty<'tcx>, + trait_ty: Ty<'tcx>, preds: &ty::List>, ) -> InterpResult<'tcx, bool> { ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; + ensure_monomorphic_enough(ecx.tcx.tcx, trait_ty)?; let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env); From 566b8ef86f7c86297af9e740c35acd0cd76346a1 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:08:34 +0800 Subject: [PATCH 10/14] Make has_trait a method of Type, and rejig de-duplication. --- .../src/const_eval/machine.rs | 19 +++-------- .../src/const_eval/type_info.rs | 3 ++ .../src/interpret/intrinsics.rs | 11 ++----- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/util.rs | 16 +++++++--- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/mem/type_info.rs | 32 ++++++++++--------- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c2b1044e03515..2a08c5416efe0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::interpret::{Pointer, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::{bug, mir, span_bug}; +use rustc_middle::{bug, mir}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::FnAbi; use tracing::debug; @@ -24,7 +24,7 @@ use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, - throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_predicates, + throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_dyn_trait, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -597,19 +597,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let type_from_type_id = ecx.read_type_id(&args[0])?; let trait_from_type_id = ecx.read_type_id(&args[1])?; - let ty::Dynamic(predicates, _) = trait_from_type_id.kind() else { - span_bug!( - ecx.find_closest_untracked_caller_location(), - "Invalid type provided to type_id_implements_trait. The second parameter must represent a dyn Trait, instead you gave us {trait_from_type_id}." - ); - }; - - let implements = type_implements_predicates( - ecx, - type_from_type_id, - trait_from_type_id, - predicates, - )?; + let (implements, _) = + type_implements_dyn_trait(ecx, type_from_type_id, trait_from_type_id)?; ecx.write_scalar(Scalar::from_bool(implements), dest)?; } diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index f8881f0968bb4..bbb20f8833470 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -172,6 +172,9 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { }; self.write_discriminant(variant_index, &field_dest)?; } + sym::id => { + self.write_type_id(ty, &field_dest)?; + } other => span_bug!(self.tcx.span, "unknown `Type` field {other}"), } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d79c0459790fe..d9f210b960771 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -24,7 +24,7 @@ use super::{ }; use crate::fluent_generated as fluent; use crate::interpret::Writeable; -use crate::interpret::util::type_implements_predicates; +use crate::interpret::util::type_implements_dyn_trait; #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum MulAddType { @@ -224,14 +224,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let tp_ty = instance.args.type_at(0); let result_ty = instance.args.type_at(1); - let ty::Dynamic(preds, _) = result_ty.kind() else { - span_bug!( - self.find_closest_untracked_caller_location(), - "Invalid type provided to vtable_for::. U must be dyn Trait, got {result_ty}." - ); - }; + let (implements_trait, preds) = type_implements_dyn_trait(self, tp_ty, result_ty)?; - if type_implements_predicates(self, tp_ty, result_ty, preds)? { + if implements_trait { let vtable_ptr = self.get_vtable_ptr(tp_ty, preds)?; // Writing a non-null pointer into an `Option` will automatically make it `Some`. self.write_pointer(vtable_ptr, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 5c8ebabe1a1c3..22554b064ebf0 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -38,6 +38,6 @@ use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo}; pub use self::util::EnteredTraceSpan; -pub(crate) use self::util::{create_static_alloc, type_implements_predicates}; +pub(crate) use self::util::{create_static_alloc, type_implements_dyn_trait}; pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 85e770d384920..57a02769643b7 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -4,7 +4,7 @@ use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{PolyExistentialPredicate, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; -use rustc_middle::{mir, ty}; +use rustc_middle::{mir, span_bug, ty}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; @@ -14,15 +14,21 @@ use crate::interpret::Machine; /// Checks if a type implements predicates. /// Calls `ensure_monomorphic_enough` on `ty` and `trait_ty` for you. -pub(crate) fn type_implements_predicates<'tcx, M: Machine<'tcx>>( +pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>( ecx: &mut InterpCx<'tcx, M>, ty: Ty<'tcx>, trait_ty: Ty<'tcx>, - preds: &ty::List>, -) -> InterpResult<'tcx, bool> { +) -> InterpResult<'tcx, (bool, &'tcx ty::List>)> { ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; ensure_monomorphic_enough(ecx.tcx.tcx, trait_ty)?; + let ty::Dynamic(preds, _) = trait_ty.kind() else { + span_bug!( + ecx.find_closest_untracked_caller_location(), + "Invalid type provided to type_implements_predicates. U must be dyn Trait, got {trait_ty}." + ); + }; + let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env); let ocx = ObligationCtxt::new(&infcx); @@ -38,7 +44,7 @@ pub(crate) fn type_implements_predicates<'tcx, M: Machine<'tcx>>( // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); - interp_ok(regions_are_valid && type_impls_trait) + interp_ok((regions_are_valid && type_impls_trait, preds)) } /// Checks whether a type contains generic parameters which must be instantiated. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e65731b5dd472..26b7b9da52dbe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1239,6 +1239,7 @@ symbols! { i128_legacy_fn_min_value, i128_legacy_mod, i128_type, + id, ident, if_let, if_let_guard, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index e0a091e9692c4..920f0526c7aa2 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -15,6 +15,8 @@ pub struct Type { pub kind: TypeKind, /// Size of the type. `None` if it is unsized pub size: Option, + /// `TypeId` that the type was gathered from. + pub id: TypeId, } impl TypeId { @@ -25,40 +27,40 @@ impl TypeId { pub const fn info(self) -> Type { type_of(self) } +} + +impl Type { + /// Returns the type information of the generic type parameter. + #[unstable(feature = "type_info", issue = "146922")] + #[rustc_const_unstable(feature = "type_info", issue = "146922")] + // FIXME(reflection): don't require the 'static bound + pub const fn of() -> Self { + const { TypeId::of::().info() } + } - /// Checks if the type represented by the `TypeId` implements the trait. + /// Checks if the type has the trait. /// It can only be called at compile time. pub const fn has_trait> + ?Sized + 'static>( self, ) -> bool { - type_id_implements_trait(self, TypeId::of::()) + type_id_implements_trait(self.id, TypeId::of::()) } - /// Checks if the type represented by the `TypeId` implements the trait represented by the secondary `TypeId`. + /// Checks if the type has the trait represented by the `TypeId`. /// Returns `None` if the `trait_represented_by_type_id` is not a trait represented by type id. /// It can only be called at compile time. pub const fn has_trait_represented_by_type_id( self, - trait_represented_by_type_id: Self, + trait_represented_by_type_id: TypeId, ) -> Option { if type_id_is_trait(trait_represented_by_type_id) { - Some(type_id_implements_trait(self, trait_represented_by_type_id)) + Some(type_id_implements_trait(self.id, trait_represented_by_type_id)) } else { None } } } -impl Type { - /// Returns the type information of the generic type parameter. - #[unstable(feature = "type_info", issue = "146922")] - #[rustc_const_unstable(feature = "type_info", issue = "146922")] - // FIXME(reflection): don't require the 'static bound - pub const fn of() -> Self { - const { TypeId::of::().info() } - } -} - /// Compile-time type information. #[derive(Debug)] #[non_exhaustive] From f2ee7144b2e0ef53da3ee9eb0f09a64cc9eb5e38 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:16:12 +0800 Subject: [PATCH 11/14] Fix test. --- library/coretests/tests/mem/type_info.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 4cfc74c085209..3efb39f79955e 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -300,8 +300,8 @@ fn test_implements_trait() { impl Blah for Garlic {} const { - assert!(TypeId::of::().implements_trait::()); - assert!(TypeId::of::().implements_trait::()); - assert!(!TypeId::of::<*const Box>().implements_trait::()); + assert!(TypeId::of::().info().has_trait::()); + assert!(TypeId::of::().info().has_trait::()); + assert!(!TypeId::of::<*const Box>().info().has_trait::()); } } From d4d51329a8556e6b89f6cc2cb46d6370003794e3 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Thu, 29 Jan 2026 06:50:03 +0800 Subject: [PATCH 12/14] fixup! Fix typos: 'occured' -> 'occurred' and 'non_existant' -> 'non_existent' --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index efcd9f58636c1..85eff7c80277b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit efcd9f58636c1990393d495159045d9c35e43b8f +Subproject commit 85eff7c80277b57f78b11e28d14154ab12fcf643 From fc1413e3214be0f8ac68c5218e3f829817c8db12 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Thu, 29 Jan 2026 07:05:20 +0800 Subject: [PATCH 13/14] Dog food reflection instead of using a new intrinsic. --- compiler/rustc_const_eval/src/const_eval/machine.rs | 7 ------- compiler/rustc_hir_analysis/src/check/intrinsic.rs | 7 ------- compiler/rustc_span/src/symbol.rs | 1 - library/core/src/intrinsics/mod.rs | 9 --------- library/core/src/mem/type_info.rs | 6 ++++-- 5 files changed, 4 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 2a08c5416efe0..89a9008becf2b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -586,13 +586,6 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } } - // TODO: Remove this and replace with reflection. Blocked on reflection supporting dyn traits. - sym::type_id_is_trait => { - let kind = ecx.read_type_id(&args[0])?.kind(); - let is_trait = matches!(kind, ty::Dynamic(..)); - ecx.write_scalar(Scalar::from_bool(is_trait), dest)?; - } - sym::type_id_implements_trait => { let type_from_type_id = ecx.read_type_id(&args[0])?; let trait_from_type_id = ecx.read_type_id(&args[1])?; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 3533ca038b827..e4364a645ba3c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -214,7 +214,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::type_id | sym::type_id_eq | sym::type_id_implements_trait - | sym::type_id_is_trait | sym::type_name | sym::type_of | sym::ub_checks @@ -330,12 +329,6 @@ pub(crate) fn check_intrinsic_type( vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(); 2], tcx.types.bool, ), - sym::type_id_is_trait => ( - 0, - 0, - vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap()], - tcx.types.bool, - ), sym::type_of => ( 0, 0, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 26b7b9da52dbe..2066b75da0095 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2341,7 +2341,6 @@ symbols! { type_id, type_id_eq, type_id_implements_trait, - type_id_is_trait, type_info, type_ir, type_ir_infer_ctxt_like, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 628190889394c..74b112bd6b05a 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2852,15 +2852,6 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; #[rustc_intrinsic_const_stable_indirect] pub const unsafe fn align_of_val(ptr: *const T) -> usize; -/// Check if a type represented by a `TypeId` is a dyn Trait. -/// It can only be called at compile time, the backends do -/// not implement it. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_is_trait(_trait: crate::any::TypeId) -> bool { - panic!("`TypeId::implements_trait_represented_by_type_id` can only be called at compile-time") -} - /// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. /// It can only be called at compile time, the backends do /// not implement it. diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 920f0526c7aa2..94f469eaa997d 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -2,7 +2,7 @@ //! runtime or const-eval processable way. use crate::any::TypeId; -use crate::intrinsics::{type_id_implements_trait, type_id_is_trait, type_of}; +use crate::intrinsics::{type_id_implements_trait, type_of}; use crate::ptr; /// Compile-time type information. @@ -49,11 +49,13 @@ impl Type { /// Checks if the type has the trait represented by the `TypeId`. /// Returns `None` if the `trait_represented_by_type_id` is not a trait represented by type id. /// It can only be called at compile time. + #[unstable(feature = "type_info", issue = "146922")] + #[rustc_const_unstable(feature = "type_info", issue = "146922")] pub const fn has_trait_represented_by_type_id( self, trait_represented_by_type_id: TypeId, ) -> Option { - if type_id_is_trait(trait_represented_by_type_id) { + if matches!(trait_represented_by_type_id.info().kind, TypeKind::DynTrait(_)) { Some(type_id_implements_trait(self.id, trait_represented_by_type_id)) } else { None From 0dea0857dfb469271e14cadfd8a14dc88200a047 Mon Sep 17 00:00:00 2001 From: Katt <51190960+coolcatcoder@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:01:48 +0800 Subject: [PATCH 14/14] Fix the 64 bit dump of reflection. --- tests/ui/reflection/dump.bit64.run.stdout | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index efae226539515..dc37bd76fb272 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -20,6 +20,7 @@ Type { size: Some( 2, ), + id: TypeId(0x5a16e6fbf8293c4c38740f6ab3f64621), } Type { kind: Array( @@ -31,6 +32,7 @@ Type { size: Some( 2, ), + id: TypeId(0xe09e770f1c1da76825e6290f984ddaf7), } Type { kind: Int( @@ -42,6 +44,7 @@ Type { size: Some( 1, ), + id: TypeId(0x12427c993eca190c841e0d92c5b7a45d), } Type { kind: Int( @@ -53,6 +56,7 @@ Type { size: Some( 4, ), + id: TypeId(0x56ced5e4a15bd89050bb9674fa2df013), } Type { kind: Int( @@ -64,6 +68,7 @@ Type { size: Some( 8, ), + id: TypeId(0xae6c4318bb07632e00428affbea41961), } Type { kind: Int( @@ -75,6 +80,7 @@ Type { size: Some( 16, ), + id: TypeId(0xc7164498f3902dde0d8194a7b9733e79), } Type { kind: Int( @@ -86,6 +92,7 @@ Type { size: Some( 8, ), + id: TypeId(0x1e5f92831c560aac8658b980a22e60b0), } Type { kind: Int( @@ -97,6 +104,7 @@ Type { size: Some( 1, ), + id: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), } Type { kind: Int( @@ -108,6 +116,7 @@ Type { size: Some( 4, ), + id: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), } Type { kind: Int( @@ -119,6 +128,7 @@ Type { size: Some( 8, ), + id: TypeId(0x9ed91be891e304132cb86891e578f4a5), } Type { kind: Int( @@ -130,6 +140,7 @@ Type { size: Some( 16, ), + id: TypeId(0x7bf7411d57d603e9fb393892a9c3f362), } Type { kind: Int( @@ -141,18 +152,21 @@ Type { size: Some( 8, ), + id: TypeId(0x763d199bccd319899208909ed1a860c6), } Type { kind: Other, size: Some( 4, ), + id: TypeId(0x78c34ce87517aee8f0d54cc3ea348028), } Type { kind: Other, size: Some( 24, ), + id: TypeId(0x8ed28b76f102b777afcc7a07749d45fe), } Type { kind: Reference( @@ -164,6 +178,7 @@ Type { size: Some( 16, ), + id: TypeId(0x4d13f2e9be6854d4529cc187d26d3e83), } Type { kind: Reference( @@ -175,6 +190,7 @@ Type { size: Some( 16, ), + id: TypeId(0xb98b1b7157a6417863eb502cd6cb5d6d), } Type { kind: Reference( @@ -186,12 +202,14 @@ Type { size: Some( 16, ), + id: TypeId(0x03f6aa200663725e076283e0711c66aa), } Type { kind: Str( Str, ), size: None, + id: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c), } Type { kind: Slice( @@ -200,6 +218,7 @@ Type { }, ), size: None, + id: TypeId(0x641e3def269c37acc6dcb92bf8c5f196), } Type { kind: Reference( @@ -211,6 +230,7 @@ Type { size: Some( 8, ), + id: TypeId(0x8a8d25435c9aa1ed611bd54eddb095c4), } Type { kind: Reference( @@ -222,4 +242,5 @@ Type { size: Some( 8, ), + id: TypeId(0x57bb24072c78596db60e68f83b5de67b), }