Rollup merge of #151222 - reflect-references, r=oli-obk

feat: Support references in reflection type info

Tracking issue: https://github.com/rust-lang/rust/issues/146922 `#![feature(type_info)]`

Based on rust-lang/rust#151119 implementation for pointers for consistency

r? oli-obk
This commit is contained in:
Stuart Cook 2026-01-17 11:47:20 +11:00 committed by GitHub
commit 2956932345
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 161 additions and 8 deletions

View file

@ -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(())
}
}

View file

@ -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,

View file

@ -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,
}

View file

@ -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::<str>() }) 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::<u8>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}
// Mutable pointer.
match const { Type::of::<&mut u64>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<u64>());
assert!(reference.mutable);
}
_ => unreachable!(),
}
// Wide pointer.
match const { Type::of::<&dyn Any>() }.kind {
TypeKind::Reference(reference) => {
assert_eq!(reference.pointee, TypeId::of::<dyn Any>());
assert!(!reference.mutable);
}
_ => unreachable!(),
}
}

View file

@ -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,
),
}

View file

@ -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,
),
}

View file

@ -40,5 +40,6 @@ fn main() {
Foo, Bar,
&Unsized, &str, &[u8],
str, [u8],
&u8, &mut u8,
}
}