Skip to content

Commit ac7ba99

Browse files
authored
Rollup merge of #156403 - SpriteOvO:type-info-refactor-variant, r=oli-obk
Add `TypeId` methods `variants` `fields` `field` for `type_info` Tracking issue #146922 - Adds `fn TypeId::variants` returns the number of variants, for struct and union and primitive types, it's always 1. - Adds `fn TypeId::fields` returns the number of fields. - Adds `fn TypeId::field` returns a field representing type `FieldId`. - Adds a new type `FieldId`, which is a wrapper of `FieldRepresentingType`'s `TypeId`. For methods `{fields,field}`, if indexing out of bounds, a compile-time error will be raised. Regarding the removal of `Type` items, this will be done in a later PR in one go. r? @oli-obk
2 parents 54352a0 + b513e53 commit ac7ba99

9 files changed

Lines changed: 456 additions & 4 deletions

File tree

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow};
22
use std::hash::Hash;
33
use std::{fmt, mem};
44

5-
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size};
5+
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
66
use rustc_ast::Mutability;
77
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
88
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -622,6 +622,75 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
622622
ecx.write_discriminant(variant_index, dest)?;
623623
}
624624

625+
sym::type_id_fields => {
626+
let ty = ecx.read_type_id(&args[0])?;
627+
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
628+
629+
let variants_num =
630+
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
631+
if variant_idx >= variants_num {
632+
throw_ub!(BoundsCheckFailed {
633+
len: variants_num as u64,
634+
index: variant_idx as u64
635+
});
636+
}
637+
638+
let fields_num = match ty.kind() {
639+
ty::Adt(adt_def, _) => {
640+
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
641+
variant_def.fields.len()
642+
}
643+
ty::Tuple(fields) => fields.len(),
644+
_ => 0, // Other types have no fields
645+
};
646+
647+
ecx.write_scalar(Scalar::from_target_usize(fields_num as u64, ecx), dest)?;
648+
}
649+
650+
sym::type_id_field_representing_type => {
651+
let ty = ecx.read_type_id(&args[0])?;
652+
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
653+
let field_idx = ecx.read_target_usize(&args[2])? as usize;
654+
655+
let variants_num =
656+
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
657+
if variant_idx >= variants_num {
658+
throw_ub!(BoundsCheckFailed {
659+
len: variants_num as u64,
660+
index: variant_idx as u64
661+
});
662+
}
663+
664+
let fields_num = match ty.kind() {
665+
ty::Adt(adt_def, _) => {
666+
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
667+
variant_def.fields.len()
668+
}
669+
ty::Tuple(fields) => fields.len(),
670+
_ => 0, // Other types have no fields
671+
};
672+
if field_idx >= fields_num {
673+
throw_ub!(BoundsCheckFailed {
674+
len: fields_num as u64,
675+
index: field_idx as u64
676+
});
677+
}
678+
679+
let frt = Ty::new_field_representing_type(
680+
*ecx.tcx,
681+
ty,
682+
VariantIdx::from_usize(variant_idx),
683+
FieldIdx::from_usize(field_idx),
684+
);
685+
ecx.write_type_id(frt, dest)?;
686+
}
687+
688+
sym::type_id_variants => {
689+
let ty = ecx.read_type_id(&args[0])?;
690+
let variants_num = ty.ty_adt_def().map(|def| def.variants().len()).unwrap_or(1);
691+
ecx.write_scalar(Scalar::from_target_usize(variants_num as u64, ecx), dest)?;
692+
}
693+
625694
sym::field_offset => {
626695
let frt_ty = instance.args.type_at(0);
627696
ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?;
@@ -643,6 +712,20 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
643712
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
644713
}
645714

715+
sym::field_representing_type_actual_type_id => {
716+
let frt_ty = ecx.read_type_id(&args[0])?;
717+
718+
let field_ty = if let ty::Adt(def, args) = frt_ty.kind()
719+
&& let Some(FieldInfo { ty, .. }) =
720+
def.field_representing_type_info(ecx.tcx.tcx, args)
721+
{
722+
ecx.tcx.erase_and_anonymize_regions(ty)
723+
} else {
724+
span_bug!(ecx.cur_span(), "expected field representing type, got {frt_ty}")
725+
};
726+
ecx.write_type_id(field_ty, dest)?;
727+
}
728+
646729
_ => {
647730
// We haven't handled the intrinsic, let's see if we can use a fallback body.
648731
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
114114
| sym::fadd_algebraic
115115
| sym::fdiv_algebraic
116116
| sym::field_offset
117+
| sym::field_representing_type_actual_type_id
117118
| sym::floorf16
118119
| sym::floorf32
119120
| sym::floorf64
@@ -213,6 +214,9 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
213214
| sym::truncf128
214215
| sym::type_id
215216
| sym::type_id_eq
217+
| sym::type_id_field_representing_type
218+
| sym::type_id_fields
219+
| sym::type_id_variants
216220
| sym::type_id_vtable
217221
| sym::type_name
218222
| sym::type_of
@@ -319,6 +323,11 @@ pub(crate) fn check_intrinsic_type(
319323
sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
320324
sym::type_id => (1, 0, vec![], type_id_ty()),
321325
sym::type_id_eq => (0, 0, vec![type_id_ty(), type_id_ty()], tcx.types.bool),
326+
sym::type_id_field_representing_type => {
327+
(0, 0, vec![type_id_ty(), tcx.types.usize, tcx.types.usize], type_id_ty())
328+
}
329+
sym::type_id_fields => (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.usize),
330+
sym::type_id_variants => (0, 0, vec![type_id_ty()], tcx.types.usize),
322331
sym::type_id_vtable => {
323332
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span);
324333
let dyn_metadata_adt_ref = tcx.adt_def(dyn_metadata);
@@ -339,6 +348,7 @@ pub(crate) fn check_intrinsic_type(
339348
vec![type_id_ty()],
340349
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
341350
),
351+
sym::field_representing_type_actual_type_id => (0, 0, vec![type_id_ty()], type_id_ty()),
342352
sym::offload => (
343353
3,
344354
0,

compiler/rustc_span/src/symbol.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ symbols! {
948948
field_offset,
949949
field_projections,
950950
field_representing_type,
951+
field_representing_type_actual_type_id,
951952
field_representing_type_raw,
952953
field_type,
953954
fields,
@@ -2098,6 +2099,9 @@ symbols! {
20982099
type_changing_struct_update,
20992100
type_id,
21002101
type_id_eq,
2102+
type_id_field_representing_type,
2103+
type_id_fields,
2104+
type_id_variants,
21012105
type_id_vtable,
21022106
type_info,
21032107
type_ir,

library/core/src/any.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ impl TypeId {
829829
}
830830
}
831831

832-
fn as_u128(self) -> u128 {
832+
pub(crate) fn as_u128(self) -> u128 {
833833
let mut bytes = [0; 16];
834834

835835
// This is a provenance-stripping memcpy.

library/core/src/intrinsics/mod.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,11 +2941,57 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool {
29412941

29422942
/// Gets the size of the type represented by this `TypeId`.
29432943
///
2944-
/// The stabilized version of this intrinsic is [`core::any::TypeId::size`].
2944+
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`].
29452945
#[rustc_intrinsic]
29462946
#[unstable(feature = "core_intrinsics", issue = "none")]
29472947
pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option<usize> {
2948-
panic!("`Type::size` can only be called at compile-time")
2948+
panic!("`TypeId::size` can only be called at compile-time")
2949+
}
2950+
2951+
/// Gets the number of variants of the type represented by this `TypeId`.
2952+
///
2953+
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`].
2954+
#[rustc_intrinsic]
2955+
#[unstable(feature = "core_intrinsics", issue = "none")]
2956+
pub const fn type_id_variants(_id: crate::any::TypeId) -> usize {
2957+
panic!("`TypeId::variants` can only be called at compile-time")
2958+
}
2959+
2960+
/// Gets the number of fields at the given `variant_index` represented by this `TypeId`.
2961+
///
2962+
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`].
2963+
#[rustc_intrinsic]
2964+
#[unstable(feature = "core_intrinsics", issue = "none")]
2965+
pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize {
2966+
panic!("`TypeId::fields` can only be called at compile-time")
2967+
}
2968+
2969+
/// Gets the [`FieldRepresentingType`]'s `TypeId` at the given index of the type represented by this `TypeId`.
2970+
///
2971+
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::field`].
2972+
///
2973+
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
2974+
#[rustc_intrinsic]
2975+
#[unstable(feature = "core_intrinsics", issue = "none")]
2976+
pub const fn type_id_field_representing_type(
2977+
_id: crate::any::TypeId,
2978+
_variant_index: usize,
2979+
_field_index: usize,
2980+
) -> crate::any::TypeId {
2981+
panic!("`TypeId::field` can only be called at compile-time")
2982+
}
2983+
2984+
/// Gets the actual field `TypeId` of the [`FieldRepresentingType`]'s `TypeId`.
2985+
///
2986+
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::type_id`].
2987+
///
2988+
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
2989+
#[rustc_intrinsic]
2990+
#[unstable(feature = "core_intrinsics", issue = "none")]
2991+
pub const fn field_representing_type_actual_type_id(
2992+
_frt_type_id: crate::any::TypeId,
2993+
) -> crate::any::TypeId {
2994+
panic!("`FieldId::type_id` can only be called at compile-time")
29492995
}
29502996

29512997
/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.

0 commit comments

Comments
 (0)