Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/type_info.rs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pay special attention to my changes in this file, as this is where I feel least confident in my understanding of the code!

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -56,14 +56,21 @@ 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
}
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
Expand Down Expand Up @@ -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(())
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ symbols! {
Arc,
ArcWeak,
Argument,
Array,
ArrayIntoIter,
AsMut,
AsRef,
Expand Down Expand Up @@ -939,6 +940,7 @@ symbols! {
eii_impl,
eii_internals,
eii_shared_macro,
element_ty,
emit,
emit_enum,
emit_enum_variant,
Expand Down
13 changes: 13 additions & 0 deletions library/core/src/mem/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ impl Type {
pub enum TypeKind {
/// Tuples.
Tuple(Tuple),
/// Arrays.
Array(Array),
/// Primitives
/// FIXME(#146922): disambiguate further
Leaf,
Expand All @@ -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,
}
1 change: 1 addition & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 2 additions & 0 deletions library/coretests/tests/mem.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod type_info;

use core::mem::*;
use core::{array, ptr};
use std::cell::Cell;
Expand Down
56 changes: 56 additions & 0 deletions library/coretests/tests/mem/type_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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!(),
}
}

#[test]
fn test_tuples() {
fn assert_tuple_arity<T: 'static, const N: usize>() {
match const { Type::of::<T>() }.kind {
TypeKind::Tuple(tup) => {
assert_eq!(tup.fields.len(), N);
}
_ => unreachable!(),
}
}

assert_tuple_arity::<(), 0>();
assert_tuple_arity::<(u8,), 1>();
assert_tuple_arity::<(u8, u8), 2>();

const {
match Type::of::<(u8, u8)>().kind {
TypeKind::Tuple(tup) => {
let [a, b] = tup.fields else { unreachable!() };

assert!(a.offset == 0);
assert!(b.offset == 1);

match (a.ty.info().kind, b.ty.info().kind) {
(TypeKind::Leaf, TypeKind::Leaf) => {}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
}
1 change: 1 addition & 0 deletions tests/ui/reflection/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/reflection/dump.run.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Tuple(
],
},
)
Array(
Array {
element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
len: 2,
},
)
Other
Other
Other
Expand Down
36 changes: 0 additions & 36 deletions tests/ui/reflection/tuples.rs

This file was deleted.

Loading