mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-30 04:56:25 +03:00
Rollup merge of #156403 - SpriteOvO:type-info-refactor-variant, r=oli-obk
Add `TypeId` methods `variants` `fields` `field` for `type_info` Tracking issue rust-lang/rust#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
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
use std::hash::Hash;
|
||||
use std::{fmt, mem};
|
||||
|
||||
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size};
|
||||
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
@@ -622,6 +622,75 @@ fn call_intrinsic(
|
||||
ecx.write_discriminant(variant_index, dest)?;
|
||||
}
|
||||
|
||||
sym::type_id_fields => {
|
||||
let ty = ecx.read_type_id(&args[0])?;
|
||||
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
|
||||
|
||||
let variants_num =
|
||||
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
|
||||
if variant_idx >= variants_num {
|
||||
throw_ub!(BoundsCheckFailed {
|
||||
len: variants_num as u64,
|
||||
index: variant_idx as u64
|
||||
});
|
||||
}
|
||||
|
||||
let fields_num = match ty.kind() {
|
||||
ty::Adt(adt_def, _) => {
|
||||
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
|
||||
variant_def.fields.len()
|
||||
}
|
||||
ty::Tuple(fields) => fields.len(),
|
||||
_ => 0, // Other types have no fields
|
||||
};
|
||||
|
||||
ecx.write_scalar(Scalar::from_target_usize(fields_num as u64, ecx), dest)?;
|
||||
}
|
||||
|
||||
sym::type_id_field_representing_type => {
|
||||
let ty = ecx.read_type_id(&args[0])?;
|
||||
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
|
||||
let field_idx = ecx.read_target_usize(&args[2])? as usize;
|
||||
|
||||
let variants_num =
|
||||
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
|
||||
if variant_idx >= variants_num {
|
||||
throw_ub!(BoundsCheckFailed {
|
||||
len: variants_num as u64,
|
||||
index: variant_idx as u64
|
||||
});
|
||||
}
|
||||
|
||||
let fields_num = match ty.kind() {
|
||||
ty::Adt(adt_def, _) => {
|
||||
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
|
||||
variant_def.fields.len()
|
||||
}
|
||||
ty::Tuple(fields) => fields.len(),
|
||||
_ => 0, // Other types have no fields
|
||||
};
|
||||
if field_idx >= fields_num {
|
||||
throw_ub!(BoundsCheckFailed {
|
||||
len: fields_num as u64,
|
||||
index: field_idx as u64
|
||||
});
|
||||
}
|
||||
|
||||
let frt = Ty::new_field_representing_type(
|
||||
*ecx.tcx,
|
||||
ty,
|
||||
VariantIdx::from_usize(variant_idx),
|
||||
FieldIdx::from_usize(field_idx),
|
||||
);
|
||||
ecx.write_type_id(frt, dest)?;
|
||||
}
|
||||
|
||||
sym::type_id_variants => {
|
||||
let ty = ecx.read_type_id(&args[0])?;
|
||||
let variants_num = ty.ty_adt_def().map(|def| def.variants().len()).unwrap_or(1);
|
||||
ecx.write_scalar(Scalar::from_target_usize(variants_num as u64, ecx), dest)?;
|
||||
}
|
||||
|
||||
sym::field_offset => {
|
||||
let frt_ty = instance.args.type_at(0);
|
||||
ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?;
|
||||
@@ -643,6 +712,20 @@ fn call_intrinsic(
|
||||
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
|
||||
}
|
||||
|
||||
sym::field_representing_type_actual_type_id => {
|
||||
let frt_ty = ecx.read_type_id(&args[0])?;
|
||||
|
||||
let field_ty = if let ty::Adt(def, args) = frt_ty.kind()
|
||||
&& let Some(FieldInfo { ty, .. }) =
|
||||
def.field_representing_type_info(ecx.tcx.tcx, args)
|
||||
{
|
||||
ecx.tcx.erase_and_anonymize_regions(ty)
|
||||
} else {
|
||||
span_bug!(ecx.cur_span(), "expected field representing type, got {frt_ty}")
|
||||
};
|
||||
ecx.write_type_id(field_ty, dest)?;
|
||||
}
|
||||
|
||||
_ => {
|
||||
// We haven't handled the intrinsic, let's see if we can use a fallback body.
|
||||
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
|
||||
|
||||
@@ -114,6 +114,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
|
||||
| sym::fadd_algebraic
|
||||
| sym::fdiv_algebraic
|
||||
| sym::field_offset
|
||||
| sym::field_representing_type_actual_type_id
|
||||
| sym::floorf16
|
||||
| sym::floorf32
|
||||
| sym::floorf64
|
||||
@@ -213,6 +214,9 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
|
||||
| sym::truncf128
|
||||
| sym::type_id
|
||||
| sym::type_id_eq
|
||||
| sym::type_id_field_representing_type
|
||||
| sym::type_id_fields
|
||||
| sym::type_id_variants
|
||||
| sym::type_id_vtable
|
||||
| sym::type_name
|
||||
| sym::type_of
|
||||
@@ -319,6 +323,11 @@ pub(crate) fn check_intrinsic_type(
|
||||
sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
|
||||
sym::type_id => (1, 0, vec![], type_id_ty()),
|
||||
sym::type_id_eq => (0, 0, vec![type_id_ty(), type_id_ty()], tcx.types.bool),
|
||||
sym::type_id_field_representing_type => {
|
||||
(0, 0, vec![type_id_ty(), tcx.types.usize, tcx.types.usize], type_id_ty())
|
||||
}
|
||||
sym::type_id_fields => (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.usize),
|
||||
sym::type_id_variants => (0, 0, vec![type_id_ty()], tcx.types.usize),
|
||||
sym::type_id_vtable => {
|
||||
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span);
|
||||
let dyn_metadata_adt_ref = tcx.adt_def(dyn_metadata);
|
||||
@@ -339,6 +348,7 @@ pub(crate) fn check_intrinsic_type(
|
||||
vec![type_id_ty()],
|
||||
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
|
||||
),
|
||||
sym::field_representing_type_actual_type_id => (0, 0, vec![type_id_ty()], type_id_ty()),
|
||||
sym::offload => (
|
||||
3,
|
||||
0,
|
||||
|
||||
@@ -948,6 +948,7 @@
|
||||
field_offset,
|
||||
field_projections,
|
||||
field_representing_type,
|
||||
field_representing_type_actual_type_id,
|
||||
field_representing_type_raw,
|
||||
field_type,
|
||||
fields,
|
||||
@@ -2098,6 +2099,9 @@
|
||||
type_changing_struct_update,
|
||||
type_id,
|
||||
type_id_eq,
|
||||
type_id_field_representing_type,
|
||||
type_id_fields,
|
||||
type_id_variants,
|
||||
type_id_vtable,
|
||||
type_info,
|
||||
type_ir,
|
||||
|
||||
@@ -829,7 +829,7 @@ pub const fn trait_info_of_trait_type_id(
|
||||
}
|
||||
}
|
||||
|
||||
fn as_u128(self) -> u128 {
|
||||
pub(crate) fn as_u128(self) -> u128 {
|
||||
let mut bytes = [0; 16];
|
||||
|
||||
// This is a provenance-stripping memcpy.
|
||||
|
||||
@@ -2941,11 +2941,57 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool {
|
||||
|
||||
/// Gets the size of the type represented by this `TypeId`.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is [`core::any::TypeId::size`].
|
||||
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`].
|
||||
#[rustc_intrinsic]
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option<usize> {
|
||||
panic!("`Type::size` can only be called at compile-time")
|
||||
panic!("`TypeId::size` can only be called at compile-time")
|
||||
}
|
||||
|
||||
/// Gets the number of variants of the type represented by this `TypeId`.
|
||||
///
|
||||
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`].
|
||||
#[rustc_intrinsic]
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
pub const fn type_id_variants(_id: crate::any::TypeId) -> usize {
|
||||
panic!("`TypeId::variants` can only be called at compile-time")
|
||||
}
|
||||
|
||||
/// Gets the number of fields at the given `variant_index` represented by this `TypeId`.
|
||||
///
|
||||
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`].
|
||||
#[rustc_intrinsic]
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize {
|
||||
panic!("`TypeId::fields` can only be called at compile-time")
|
||||
}
|
||||
|
||||
/// Gets the [`FieldRepresentingType`]'s `TypeId` at the given index of the type represented by this `TypeId`.
|
||||
///
|
||||
/// The more user-friendly version of this intrinsic is [`core::any::TypeId::field`].
|
||||
///
|
||||
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
|
||||
#[rustc_intrinsic]
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
pub const fn type_id_field_representing_type(
|
||||
_id: crate::any::TypeId,
|
||||
_variant_index: usize,
|
||||
_field_index: usize,
|
||||
) -> crate::any::TypeId {
|
||||
panic!("`TypeId::field` can only be called at compile-time")
|
||||
}
|
||||
|
||||
/// Gets the actual field `TypeId` of the [`FieldRepresentingType`]'s `TypeId`.
|
||||
///
|
||||
/// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::type_id`].
|
||||
///
|
||||
/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType
|
||||
#[rustc_intrinsic]
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
pub const fn field_representing_type_actual_type_id(
|
||||
_frt_type_id: crate::any::TypeId,
|
||||
) -> crate::any::TypeId {
|
||||
panic!("`FieldId::type_id` can only be called at compile-time")
|
||||
}
|
||||
|
||||
/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//! runtime or const-eval processable way.
|
||||
|
||||
use crate::any::TypeId;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics::{self, type_id, type_of};
|
||||
use crate::marker::PointeeSized;
|
||||
use crate::ptr::DynMetadata;
|
||||
@@ -376,4 +377,201 @@ impl TypeId {
|
||||
pub const fn size(self) -> Option<usize> {
|
||||
intrinsics::size_of_type_id(self)
|
||||
}
|
||||
|
||||
/// Returns the number of variants of the type represented by this `TypeId`.
|
||||
///
|
||||
/// For enums, this is the number of variants. For structs and unions, this is always 1.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(type_info)]
|
||||
/// use std::any::TypeId;
|
||||
///
|
||||
/// assert_eq!(const { TypeId::of::<Option<()>>().variants() }, 2);
|
||||
///
|
||||
/// struct Unit;
|
||||
/// struct Point {
|
||||
/// x: u32,
|
||||
/// y: u32,
|
||||
/// }
|
||||
/// assert_eq!(const { TypeId::of::<Unit>().variants() }, 1);
|
||||
/// assert_eq!(const { TypeId::of::<Point>().variants() }, 1);
|
||||
/// assert_eq!(const { TypeId::of::<(f32, f32)>().variants() }, 1);
|
||||
/// ```
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
|
||||
pub const fn variants(self) -> usize {
|
||||
intrinsics::type_id_variants(self)
|
||||
}
|
||||
|
||||
/// Returns the number of fields at the given `variant_index` of the type represented by this `TypeId`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(type_info)]
|
||||
/// use std::any::TypeId;
|
||||
///
|
||||
/// assert_eq!(const { TypeId::of::<u32>().fields(0) }, 0);
|
||||
///
|
||||
/// struct Point {
|
||||
/// x: u32,
|
||||
/// y: u32,
|
||||
/// }
|
||||
/// assert_eq!(const { TypeId::of::<Point>().fields(0) }, 2);
|
||||
///
|
||||
/// enum Enum {
|
||||
/// Unit,
|
||||
/// Tuple(u32, u64),
|
||||
/// Struct { x: u32, y: u32, z: String },
|
||||
/// }
|
||||
/// assert_eq!(const { TypeId::of::<Enum>().fields(0) }, 0);
|
||||
/// assert_eq!(const { TypeId::of::<Enum>().fields(1) }, 2);
|
||||
/// assert_eq!(const { TypeId::of::<Enum>().fields(2) }, 3);
|
||||
/// ```
|
||||
///
|
||||
/// The variant index refers to the source order index of a variant in a type.
|
||||
///
|
||||
/// For enums, these are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
|
||||
/// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
|
||||
///
|
||||
/// ```
|
||||
/// enum Number {
|
||||
/// Seven = 7, // variant index == 0
|
||||
/// Six = 6, // variant index == 1
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Out-of-bounds indexing will be treated as a compile-time error.
|
||||
///
|
||||
/// ```compile_fail,E0080
|
||||
/// # #![feature(type_info)]
|
||||
/// # use std::any::TypeId;
|
||||
/// #
|
||||
/// # struct Point {
|
||||
/// # x: u32,
|
||||
/// # y: u32,
|
||||
/// # }
|
||||
/// # enum Enum {
|
||||
/// # Unit,
|
||||
/// # Tuple(u32, u64),
|
||||
/// # Struct { x: u32, y: u32, z: String },
|
||||
/// # }
|
||||
/// const {
|
||||
/// _ = TypeId::of::<Point>().fields(10); // error: indexing out of bounds: the len is 2 but the index is 10
|
||||
/// _ = TypeId::of::<Enum>().fields(10); // error: indexing out of bounds: the len is 3 but the index is 10
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
|
||||
pub const fn fields(self, variant_index: usize) -> usize {
|
||||
intrinsics::type_id_fields(self, variant_index)
|
||||
}
|
||||
|
||||
/// Returns the field representing type at the given index of the type represented by this `TypeId`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(type_info)]
|
||||
/// use std::any::TypeId;
|
||||
///
|
||||
/// struct Point {
|
||||
/// x: u32,
|
||||
/// y: u32,
|
||||
/// }
|
||||
/// assert_eq!(const { TypeId::of::<Point>().field(0, 0).type_id() }, TypeId::of::<u32>());
|
||||
/// assert_eq!(const { TypeId::of::<Point>().field(0, 1).type_id() }, TypeId::of::<u32>());
|
||||
///
|
||||
/// enum Enum {
|
||||
/// Unit,
|
||||
/// Tuple(u32, u64),
|
||||
/// Struct { x: u32, y: u32, z: String },
|
||||
/// }
|
||||
/// assert_eq!(const { TypeId::of::<Enum>().field(1, 0).type_id() }, TypeId::of::<u32>());
|
||||
/// assert_eq!(const { TypeId::of::<Enum>().field(2, 2).type_id() }, TypeId::of::<String>());
|
||||
/// ```
|
||||
///
|
||||
/// The variant index and field index refer to the source order index of a variant in a type and
|
||||
/// the source order index of a field in a variant, respectively.
|
||||
///
|
||||
/// For enums, variant indexes are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
|
||||
/// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
|
||||
///
|
||||
/// As for field indexes, they may not be the same as the layout order for `repr(Rust)` types, but they are for `repr(C)` types.
|
||||
///
|
||||
/// ```
|
||||
/// enum Enum {
|
||||
/// Foo, // variant index == 0
|
||||
/// Bar { // variant index == 1
|
||||
/// a: (), // field index == 0 in `Bar`
|
||||
/// b: (), // field index == 1 in `Bar`
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Out-of-bounds indexing will be treated as a compile-time error.
|
||||
///
|
||||
/// ```compile_fail,E0080
|
||||
/// # #![feature(type_info)]
|
||||
/// # use std::any::TypeId;
|
||||
/// #
|
||||
/// # struct Point {
|
||||
/// # x: u32,
|
||||
/// # y: u32,
|
||||
/// # }
|
||||
/// # enum Enum {
|
||||
/// # Unit,
|
||||
/// # Tuple(u32, u64),
|
||||
/// # Struct { x: u32, y: u32, z: String },
|
||||
/// # }
|
||||
/// const {
|
||||
/// _ = TypeId::of::<Point>().field(0, 10); // error: indexing out of bounds: the len is 2 but the index is 10
|
||||
/// _ = TypeId::of::<Enum>().field(2, 10); // error: indexing out of bounds: the len is 3 but the index is 10
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
|
||||
pub const fn field(self, variant_index: usize, field_index: usize) -> FieldId {
|
||||
FieldId {
|
||||
frt_type_id: intrinsics::type_id_field_representing_type(
|
||||
self,
|
||||
variant_index,
|
||||
field_index,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Field representing type ID. Representing a field of a struct, tuple or enum variant.
|
||||
#[derive(Copy, PartialOrd, Ord, Hash)]
|
||||
#[derive_const(Clone, PartialEq, Eq)]
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
pub struct FieldId {
|
||||
frt_type_id: TypeId,
|
||||
}
|
||||
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
impl fmt::Debug for FieldId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FieldId({:#034x})", self.frt_type_id.as_u128())
|
||||
}
|
||||
}
|
||||
|
||||
impl FieldId {
|
||||
/// Returns the `TypeId` of the actual field type.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(type_info)]
|
||||
/// use std::any::TypeId;
|
||||
///
|
||||
/// struct Point {
|
||||
/// x: u32,
|
||||
/// y: u32,
|
||||
/// }
|
||||
/// assert_eq!(
|
||||
/// const { TypeId::of::<Point>().field(0, 0).type_id() },
|
||||
/// TypeId::of::<u32>()
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
|
||||
pub const fn type_id(self) -> TypeId {
|
||||
intrinsics::field_representing_type_actual_type_id(self.frt_type_id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,26 @@ fn assert_tuple_arity<T: 'static, const N: usize>() {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
let ty_id = TypeId::of::<()>();
|
||||
assert!(ty_id.size() == Some(size_of::<()>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 0);
|
||||
|
||||
let ty_id = TypeId::of::<(u8,)>();
|
||||
assert!(ty_id.size() == Some(size_of::<(u8,)>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 1);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<u8>());
|
||||
|
||||
let ty_id = TypeId::of::<(u8, u16)>();
|
||||
assert!(ty_id.size() == Some(size_of::<(u8, u16)>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 2);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<u8>());
|
||||
assert!(ty_id.field(0, 1).type_id() == TypeId::of::<u16>());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -95,6 +115,11 @@ struct TestStruct {
|
||||
|
||||
let ty_id = TypeId::of::<TestStruct>();
|
||||
assert!(ty_id.size() == Some(size_of::<TestStruct>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 3);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<u8>());
|
||||
assert!(ty_id.field(0, 1).type_id() == TypeId::of::<u16>());
|
||||
assert!(ty_id.field(0, 2).type_id() == TypeId::of::<&u16>());
|
||||
}
|
||||
|
||||
const {
|
||||
@@ -116,6 +141,13 @@ struct NonExhaustive {
|
||||
assert!(ty.fields[0].ty == TypeId::of::<u8>());
|
||||
assert!(ty.fields[1].name == "1");
|
||||
assert!(ty.fields[1].ty == TypeId::of::<u16>());
|
||||
|
||||
let ty_id = TypeId::of::<TupleStruct>();
|
||||
assert!(ty_id.size() == Some(size_of::<TupleStruct>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 2);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<u8>());
|
||||
assert!(ty_id.field(0, 1).type_id() == TypeId::of::<u16>());
|
||||
}
|
||||
|
||||
const {
|
||||
@@ -156,6 +188,10 @@ union TestUnion {
|
||||
|
||||
let ty_id = TypeId::of::<TestUnion>();
|
||||
assert!(ty_id.size() == Some(size_of::<TestUnion>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
assert!(ty_id.fields(0) == 2);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<i16>());
|
||||
assert!(ty_id.field(0, 1).type_id() == TypeId::of::<u16>());
|
||||
}
|
||||
|
||||
const {
|
||||
@@ -212,6 +248,13 @@ enum E {
|
||||
|
||||
let ty_id = TypeId::of::<E>();
|
||||
assert!(ty_id.size() == Some(size_of::<E>()));
|
||||
assert!(ty_id.variants() == 3);
|
||||
assert!(ty_id.fields(0) == 1);
|
||||
assert!(ty_id.fields(1) == 0);
|
||||
assert!(ty_id.fields(2) == 2);
|
||||
assert!(ty_id.field(0, 0).type_id() == TypeId::of::<u32>());
|
||||
assert!(ty_id.field(2, 0).type_id() == TypeId::of::<()>());
|
||||
assert!(ty_id.field(2, 1).type_id() == TypeId::of::<&str>());
|
||||
}
|
||||
|
||||
const {
|
||||
@@ -223,6 +266,10 @@ enum E {
|
||||
|
||||
let ty_id = TypeId::of::<Option<i32>>();
|
||||
assert!(ty_id.size() == Some(size_of::<Option<i32>>()));
|
||||
assert!(ty_id.variants() == 2);
|
||||
assert!(ty_id.fields(0) == 0);
|
||||
assert!(ty_id.fields(1) == 1);
|
||||
assert!(ty_id.field(1, 0).type_id() == TypeId::of::<i32>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,43 +281,51 @@ fn test_primitives() {
|
||||
let Type { kind: Bool(_ty), .. } = (const { Type::of::<bool>() }) else { panic!() };
|
||||
let ty_id = TypeId::of::<bool>();
|
||||
assert!(ty_id.size() == Some(size_of::<bool>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Char(_ty), .. } = (const { Type::of::<char>() }) else { panic!() };
|
||||
let ty_id = TypeId::of::<char>();
|
||||
assert!(ty_id.size() == Some(size_of::<char>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Int(ty), .. } = (const { Type::of::<i32>() }) else { panic!() };
|
||||
assert!(ty.bits == 32);
|
||||
assert!(ty.signed);
|
||||
let ty_id = TypeId::of::<i32>();
|
||||
assert!(ty_id.size() == Some(size_of::<i32>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Int(ty), .. } = (const { Type::of::<isize>() }) else { panic!() };
|
||||
assert!(ty.bits as usize == size_of::<isize>() * 8);
|
||||
assert!(ty.signed);
|
||||
let ty_id = TypeId::of::<isize>();
|
||||
assert!(ty_id.size() == Some(size_of::<isize>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Int(ty), .. } = (const { Type::of::<u32>() }) else { panic!() };
|
||||
assert!(ty.bits == 32);
|
||||
assert!(!ty.signed);
|
||||
let ty_id = TypeId::of::<u32>();
|
||||
assert!(ty_id.size() == Some(size_of::<u32>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Int(ty), .. } = (const { Type::of::<usize>() }) else { panic!() };
|
||||
assert!(ty.bits as usize == size_of::<usize>() * 8);
|
||||
assert!(!ty.signed);
|
||||
let ty_id = TypeId::of::<usize>();
|
||||
assert!(ty_id.size() == Some(size_of::<usize>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Float(ty), .. } = (const { Type::of::<f32>() }) else { panic!() };
|
||||
assert!(ty.bits == 32);
|
||||
let ty_id = TypeId::of::<f32>();
|
||||
assert!(ty_id.size() == Some(size_of::<f32>()));
|
||||
assert!(ty_id.variants() == 1);
|
||||
|
||||
let Type { kind: Str(_ty), .. } = (const { Type::of::<str>() }) else { panic!() };
|
||||
let ty_id = TypeId::of::<str>();
|
||||
assert!(ty_id.size() == None);
|
||||
assert!(ty_id.variants() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#![feature(type_info)]
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
fn main() {}
|
||||
|
||||
const _: () = const {
|
||||
TypeId::of::<Option::<()>>().fields(2);
|
||||
//~^ ERROR indexing out of bounds: the len is 2 but the index is 2
|
||||
};
|
||||
|
||||
const _: () = const {
|
||||
TypeId::of::<Option::<()>>().field(0, 1);
|
||||
//~^ ERROR indexing out of bounds: the len is 0 but the index is 1
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
error[E0080]: indexing out of bounds: the len is 2 but the index is 2
|
||||
--> $DIR/variant_index_out_of_bounds.rs:8:5
|
||||
|
|
||||
LL | TypeId::of::<Option::<()>>().fields(2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `type_info::<impl TypeId>::fields`
|
||||
--> $SRC_DIR/core/src/mem/type_info.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/variant_index_out_of_bounds.rs:7:15
|
||||
|
|
||||
LL | const _: () = const {
|
||||
| _______________^
|
||||
LL | | TypeId::of::<Option::<()>>().fields(2);
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_^
|
||||
|
||||
error[E0080]: indexing out of bounds: the len is 0 but the index is 1
|
||||
--> $DIR/variant_index_out_of_bounds.rs:13:5
|
||||
|
|
||||
LL | TypeId::of::<Option::<()>>().field(0, 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_::{constant#0}` failed inside this call
|
||||
|
|
||||
note: inside `type_info::<impl TypeId>::field`
|
||||
--> $SRC_DIR/core/src/mem/type_info.rs:LL:COL
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/variant_index_out_of_bounds.rs:12:15
|
||||
|
|
||||
LL | const _: () = const {
|
||||
| _______________^
|
||||
LL | | TypeId::of::<Option::<()>>().field(0, 1);
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
Reference in New Issue
Block a user