From c7031e93c50ad46601993efe6d7e6139977bd1a2 Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Fri, 16 Jan 2026 18:31:11 +0000 Subject: [PATCH] feat: Support references in reflection type info --- .../src/const_eval/type_info.rs | 35 ++++++++++++++- compiler/rustc_span/src/symbol.rs | 2 + library/core/src/mem/type_info.rs | 13 ++++++ library/coretests/tests/mem/type_info.rs | 32 +++++++++++++- tests/ui/reflection/dump.bit32.run.stdout | 43 +++++++++++++++++-- tests/ui/reflection/dump.bit64.run.stdout | 43 +++++++++++++++++-- tests/ui/reflection/dump.rs | 1 + 7 files changed, 161 insertions(+), 8 deletions(-) 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 5d37db06d76ac..3c6064d3f87d3 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -1,4 +1,5 @@ use rustc_abi::FieldIdx; +use rustc_ast::Mutability; use rustc_hir::LangItem; use rustc_middle::mir::interpret::{CtfeProvenance, Scalar}; use rustc_middle::span_bug; @@ -103,12 +104,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { let (variant, _variant_place) = downcast(sym::Str)?; variant } + ty::Ref(_, ty, mutability) => { + let (variant, variant_place) = downcast(sym::Reference)?; + let reference_place = + self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_reference_type_info(reference_place, *ty, *mutability)?; + + variant + } ty::Adt(_, _) | ty::Foreign(_) | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(..) - | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(..) | ty::UnsafeBinder(..) @@ -279,4 +287,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { } interp_ok(()) } + + pub(crate) fn write_reference_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + ty: Ty<'tcx>, + mutability: Mutability, + ) -> InterpResult<'tcx> { + // Iterate over all fields of `type_info::Reference`. + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + // Write the `TypeId` of the reference's inner type to the `ty` field. + sym::pointee => self.write_type_id(ty, &field_place)?, + // Write the boolean representing the reference's mutability to the `mutable` field. + sym::mutable => { + self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + interp_ok(()) + } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 51920db8cd79e..f0576002354dc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -343,6 +343,7 @@ symbols! { RefCell, RefCellRef, RefCellRefMut, + Reference, Relaxed, Release, Result, @@ -1521,6 +1522,7 @@ symbols! { must_use, mut_preserve_binding_mode_2024, mut_ref, + mutable, naked, naked_asm, naked_functions, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 2e3bdb45ce052..ee647ef55840a 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -55,6 +55,8 @@ pub enum TypeKind { Float(Float), /// String slice type. Str(Str), + /// References. + Reference(Reference), /// FIXME(#146922): add all the common types Other, } @@ -133,3 +135,14 @@ pub struct Float { pub struct Str { // No additional information to provide for now. } + +/// Compile-time type information about references. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Reference { + /// The type of the value being referred to. + pub pointee: TypeId, + /// Whether this reference is mutable or not. + pub mutable: bool, +} diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index fc13637a5574c..7df632981ce1b 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -1,4 +1,4 @@ -use std::any::TypeId; +use std::any::{Any, TypeId}; use std::mem::type_info::{Type, TypeKind}; #[test] @@ -95,3 +95,33 @@ fn test_primitives() { let Type { kind: Str(_ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, None); } + +#[test] +fn test_references() { + // Immutable reference. + match const { Type::of::<&u8>() }.kind { + TypeKind::Reference(reference) => { + assert_eq!(reference.pointee, TypeId::of::()); + assert!(!reference.mutable); + } + _ => unreachable!(), + } + + // Mutable pointer. + match const { Type::of::<&mut u64>() }.kind { + TypeKind::Reference(reference) => { + assert_eq!(reference.pointee, TypeId::of::()); + assert!(reference.mutable); + } + _ => unreachable!(), + } + + // Wide pointer. + match const { Type::of::<&dyn Any>() }.kind { + TypeKind::Reference(reference) => { + assert_eq!(reference.pointee, TypeId::of::()); + assert!(!reference.mutable); + } + _ => unreachable!(), + } +} diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index 483efdbbd12ab..8d0398bdd53ae 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -155,19 +155,34 @@ Type { ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0xda1b6da9bd297bb2900de9303aadea79), + mutable: false, + }, + ), size: Some( 8, ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c), + mutable: false, + }, + ), size: Some( 8, ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0x641e3def269c37acc6dcb92bf8c5f196), + mutable: false, + }, + ), size: Some( 8, ), @@ -182,3 +197,25 @@ Type { kind: Other, size: None, } +Type { + kind: Reference( + Reference { + pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + mutable: false, + }, + ), + size: Some( + 4, + ), +} +Type { + kind: Reference( + Reference { + pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + mutable: true, + }, + ), + size: Some( + 4, + ), +} diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index 681e81b71d56b..3564922fc1714 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -155,19 +155,34 @@ Type { ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0xda1b6da9bd297bb2900de9303aadea79), + mutable: false, + }, + ), size: Some( 16, ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0x474ccf3b5db264ef53916706f7d7bb2c), + mutable: false, + }, + ), size: Some( 16, ), } Type { - kind: Other, + kind: Reference( + Reference { + pointee: TypeId(0x641e3def269c37acc6dcb92bf8c5f196), + mutable: false, + }, + ), size: Some( 16, ), @@ -182,3 +197,25 @@ Type { kind: Other, size: None, } +Type { + kind: Reference( + Reference { + pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + mutable: false, + }, + ), + size: Some( + 8, + ), +} +Type { + kind: Reference( + Reference { + pointee: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + mutable: true, + }, + ), + size: Some( + 8, + ), +} diff --git a/tests/ui/reflection/dump.rs b/tests/ui/reflection/dump.rs index 584b7c8ed4ae8..d42216a62fdc8 100644 --- a/tests/ui/reflection/dump.rs +++ b/tests/ui/reflection/dump.rs @@ -40,5 +40,6 @@ fn main() { Foo, Bar, &Unsized, &str, &[u8], str, [u8], + &u8, &mut u8, } }