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
85 changes: 84 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow};
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};
Expand Down Expand Up @@ -622,6 +622,75 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
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)?;
Expand All @@ -643,6 +712,20 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
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 {
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,7 @@ symbols! {
field_offset,
field_projections,
field_representing_type,
field_representing_type_actual_type_id,
field_representing_type_raw,
field_type,
fields,
Expand Down Expand Up @@ -2098,6 +2099,9 @@ symbols! {
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,
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ impl TypeId {
}
}

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

// This is a provenance-stripping memcpy.
Expand Down
50 changes: 48 additions & 2 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2939,11 +2939,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`.
Expand Down
Loading
Loading