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
4 changes: 1 addition & 3 deletions compiler/rustc_const_eval/src/const_eval/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
self.project_downcast_named(&field_dest, sym::Slice)?;
variant
}
ty::Adt(adt_def, generics) => {
self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)?
}
ty::Adt(adt_def, _) => self.write_adt_type_info(&field_dest, *adt_def)?,
ty::Bool => {
let (variant, _variant_place) =
self.project_downcast_named(&field_dest, sym::Bool)?;
Expand Down
178 changes: 6 additions & 172 deletions compiler/rustc_const_eval/src/const_eval/type_info/adt.rs
Original file line number Diff line number Diff line change
@@ -1,204 +1,38 @@
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{
AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef,
AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty,
};
use rustc_span::{bug, span_bug, sym};

use crate::const_eval::CompileTimeMachine;
use crate::interpret::{
CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok,
CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Writeable, interp_ok,
};

impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
// FIXME(type_info): No semver considerations for now
pub(crate) fn write_adt_type_info(
&mut self,
place: &impl Writeable<'tcx, CtfeProvenance>,
adt: (Ty<'tcx>, AdtDef<'tcx>),
generics: &'tcx GenericArgs<'tcx>,
adt_def: AdtDef<'tcx>,
) -> InterpResult<'tcx, VariantIdx> {
let (adt_ty, adt_def) = adt;
let variant_idx = match adt_def.adt_kind() {
AdtKind::Struct => {
let (variant, variant_place) = self.project_downcast_named(place, sym::Struct)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_struct_type_info(
place,
(adt_ty, adt_def.variant(VariantIdx::ZERO)),
generics,
)?;
let (variant, _) = self.project_downcast_named(place, sym::Struct)?;
variant
}
AdtKind::Union => {
let (variant, variant_place) = self.project_downcast_named(place, sym::Union)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_union_type_info(
place,
(adt_ty, adt_def.variant(VariantIdx::ZERO)),
generics,
)?;
let (variant, _) = self.project_downcast_named(place, sym::Union)?;
variant
}
AdtKind::Enum => {
let (variant, variant_place) = self.project_downcast_named(place, sym::Enum)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_enum_type_info(place, adt, generics)?;
let (variant, _) = self.project_downcast_named(place, sym::Enum)?;
variant
}
};
interp_ok(variant_idx)
}

pub(crate) fn write_struct_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
struct_: (Ty<'tcx>, &'tcx VariantDef),
generics: &'tcx GenericArgs<'tcx>,
) -> InterpResult<'tcx> {
let (struct_ty, struct_def) = struct_;
let struct_layout = self.layout_of(struct_ty)?;

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 {
sym::generics => self.write_generics(&field_place, generics)?,
sym::fields => {
self.write_variant_fields(field_place, struct_def, struct_layout, generics)?
}
sym::non_exhaustive => {
let is_non_exhaustive = struct_def.is_field_list_non_exhaustive();
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}

interp_ok(())
}

pub(crate) fn write_union_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
union_: (Ty<'tcx>, &'tcx VariantDef),
generics: &'tcx GenericArgs<'tcx>,
) -> InterpResult<'tcx> {
let (union_ty, union_def) = union_;
let union_layout = self.layout_of(union_ty)?;

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 {
sym::generics => self.write_generics(&field_place, generics)?,
sym::fields => {
self.write_variant_fields(field_place, union_def, union_layout, generics)?
}
sym::non_exhaustive => {
let is_non_exhaustive = union_def.is_field_list_non_exhaustive();
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}

interp_ok(())
}

pub(crate) fn write_enum_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
enum_: (Ty<'tcx>, AdtDef<'tcx>),
generics: &'tcx GenericArgs<'tcx>,
) -> InterpResult<'tcx> {
let (enum_ty, enum_def) = enum_;
let enum_layout = self.layout_of(enum_ty)?;

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 {
sym::generics => self.write_generics(&field_place, generics)?,
sym::type_id_variants => {
self.allocate_fill_and_write_slice_ptr(
&field_place,
enum_def.variants().len() as u64,
|this, i, place| {
let variant_idx = VariantIdx::from_usize(i as usize);
let variant_def = &enum_def.variants()[variant_idx];
let variant_layout = enum_layout.for_variant(this, variant_idx);
this.write_enum_variant(place, (variant_layout, &variant_def), generics)
},
)?;
}
sym::non_exhaustive => {
let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive();
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}

interp_ok(())
}

fn write_enum_variant(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
variant: (TyAndLayout<'tcx>, &'tcx VariantDef),
generics: &'tcx GenericArgs<'tcx>,
) -> InterpResult<'tcx> {
let (variant_layout, variant_def) = variant;

for (field_idx, field_def) 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_def.name {
sym::name => {
let name_place = self.allocate_str_dedup(variant_def.name.as_str())?;
let ptr = self.mplace_to_imm_ptr(&name_place, None)?;
self.write_immediate(*ptr, &field_place)?
}
sym::fields => {
self.write_variant_fields(field_place, &variant_def, variant_layout, generics)?
}
sym::non_exhaustive => {
let is_non_exhaustive = variant_def.is_field_list_non_exhaustive();
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
}
other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"),
}
}
interp_ok(())
}

// Write fields for struct, enum variants
fn write_variant_fields(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
variant_def: &'tcx VariantDef,
variant_layout: TyAndLayout<'tcx>,
generics: &'tcx GenericArgs<'tcx>,
) -> InterpResult<'tcx> {
self.allocate_fill_and_write_slice_ptr(
&place,
variant_def.fields.len() as u64,
|this, i, place| {
let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)];
let field_ty = field_def.ty(*this.tcx, generics).skip_norm_wip();
this.write_field(field_ty, place, variant_layout, Some(field_def.name), i)
},
)
}

pub(super) fn write_generics(
&mut self,
place: &impl Writeable<'tcx, CtfeProvenance>,
Expand Down
Loading