feat: support arrays in type reflection
This commit is contained in:
parent
aefa10405d
commit
e027ecdbb5
8 changed files with 81 additions and 2 deletions
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
mod type_info;
|
||||
|
||||
use core::mem::*;
|
||||
use core::{array, ptr};
|
||||
use std::cell::Cell;
|
||||
|
|
|
|||
23
library/coretests/tests/mem/type_info.rs
Normal file
23
library/coretests/tests/mem/type_info.rs
Normal 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!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ Tuple(
|
|||
],
|
||||
},
|
||||
)
|
||||
Array(
|
||||
Array {
|
||||
element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
|
||||
len: 2,
|
||||
},
|
||||
)
|
||||
Other
|
||||
Other
|
||||
Other
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue