feat: support arrays in type reflection

This commit is contained in:
BD103 2026-01-12 16:24:49 -05:00
parent aefa10405d
commit e027ecdbb5
8 changed files with 81 additions and 2 deletions

View file

@ -3,7 +3,7 @@ use rustc_hir::LangItem;
use rustc_middle::mir::interpret::CtfeProvenance;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, ScalarInt, Ty};
use rustc_middle::ty::{self, Const, ScalarInt, Ty};
use rustc_span::{Symbol, sym};
use crate::const_eval::CompileTimeMachine;
@ -56,6 +56,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
self.write_tuple_fields(tuple_place, fields, ty)?;
variant
}
ty::Array(ty, len) => {
let (variant, variant_place) = downcast(sym::Array)?;
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_array_type_info(array_place, *ty, *len)?;
variant
}
// For now just merge all primitives into one `Leaf` variant with no data
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char | ty::Bool => {
downcast(sym::Leaf)?.0
@ -63,7 +71,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
@ -172,4 +179,28 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
interp_ok(())
}
pub(crate) fn write_array_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
ty: Ty<'tcx>,
len: Const<'tcx>,
) -> InterpResult<'tcx> {
// Iterate over all fields of `type_info::Array`.
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 array's elements to the `element_ty` field.
sym::element_ty => self.write_type_id(ty, &field_place)?,
// Write the length of the array to the `len` field.
sym::len => self.write_scalar(len.to_leaf(), &field_place)?,
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}
interp_ok(())
}
}

View file

@ -162,6 +162,7 @@ symbols! {
Arc,
ArcWeak,
Argument,
Array,
ArrayIntoIter,
AsMut,
AsRef,
@ -939,6 +940,7 @@ symbols! {
eii_impl,
eii_internals,
eii_shared_macro,
element_ty,
emit,
emit_enum,
emit_enum_variant,

View file

@ -43,6 +43,8 @@ impl Type {
pub enum TypeKind {
/// Tuples.
Tuple(Tuple),
/// Arrays.
Array(Array),
/// Primitives
/// FIXME(#146922): disambiguate further
Leaf,
@ -69,3 +71,14 @@ pub struct Field {
/// Offset in bytes from the parent type
pub offset: usize,
}
/// Compile-time type information about arrays.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Array {
/// The type of each element in the array.
pub element_ty: TypeId,
/// The length of the array.
pub len: usize,
}

View file

@ -115,6 +115,7 @@
#![feature(try_blocks)]
#![feature(try_find)]
#![feature(try_trait_v2)]
#![feature(type_info)]
#![feature(uint_bit_width)]
#![feature(uint_gather_scatter_bits)]
#![feature(unsize)]

View file

@ -1,3 +1,5 @@
mod type_info;
use core::mem::*;
use core::{array, ptr};
use std::cell::Cell;

View file

@ -0,0 +1,23 @@
use std::any::TypeId;
use std::mem::type_info::{Type, TypeKind};
#[test]
fn test_arrays() {
// Normal array.
match const { Type::of::<[u16; 4]>() }.kind {
TypeKind::Array(array) => {
assert_eq!(array.element_ty, TypeId::of::<u16>());
assert_eq!(array.len, 4);
}
_ => unreachable!(),
}
// Zero-length array.
match const { Type::of::<[bool; 0]>() }.kind {
TypeKind::Array(array) => {
assert_eq!(array.element_ty, TypeId::of::<bool>());
assert_eq!(array.len, 0);
}
_ => unreachable!(),
}
}

View file

@ -22,6 +22,7 @@ struct Unsized {
fn main() {
println!("{:#?}", const { Type::of::<(u8, u8, ())>() }.kind);
println!("{:#?}", const { Type::of::<[u8; 2]>() }.kind);
println!("{:#?}", const { Type::of::<Foo>() }.kind);
println!("{:#?}", const { Type::of::<Bar>() }.kind);
println!("{:#?}", const { Type::of::<&Unsized>() }.kind);

View file

@ -16,6 +16,12 @@ Tuple(
],
},
)
Array(
Array {
element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
len: 2,
},
)
Other
Other
Other