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
21 changes: 19 additions & 2 deletions 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, Size};
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_hir::def_id::{DefId, LocalDefId};
Expand All @@ -11,7 +11,7 @@ use rustc_middle::mir::AssertMessage;
use rustc_middle::mir::interpret::ReportedErrorInfo;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement};
use rustc_middle::ty::{self, FieldInfo, Ty, TyCtxt};
use rustc_middle::ty::{self, FieldInfo, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::{Span, Symbol, sym};
use rustc_target::callconv::FnAbi;
Expand Down Expand Up @@ -605,6 +605,23 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_type_info(ty, dest)?;
}

sym::size_of_type_id => {
let ty = ecx.read_type_id(&args[0])?;
let layout = ecx.layout_of(ty)?;
let variant_index = if layout.is_sized() {
let (variant, variant_place) = ecx.project_downcast_named(dest, sym::Some)?;
let size_field_place = ecx.project_field(&variant_place, FieldIdx::ZERO)?;
ecx.write_scalar(
ScalarInt::try_from_target_usize(layout.size.bytes(), ecx.tcx.tcx).unwrap(),
&size_field_place,
)?;
variant
} else {
ecx.project_downcast_named(dest, sym::None)?.0
};
ecx.write_discriminant(variant_index, dest)?;
}

sym::field_offset => {
let frt_ty = instance.args.type_at(0);
ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?;
Expand Down
77 changes: 24 additions & 53 deletions compiler/rustc_const_eval/src/const_eval/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod adt;

use std::borrow::Cow;

use rustc_abi::{ExternAbi, FieldIdx, VariantIdx};
use rustc_abi::{ExternAbi, FieldIdx};
use rustc_ast::Mutability;
use rustc_hir::LangItem;
use rustc_middle::span_bug;
Expand All @@ -12,27 +12,11 @@ use rustc_span::{Symbol, sym};

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

impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
/// Equivalent to `project_downcast`, but identifies the variant by name instead of index.
fn downcast<'a>(
&self,
place: &(impl Writeable<'tcx, CtfeProvenance> + 'a),
name: Symbol,
) -> InterpResult<'tcx, (VariantIdx, impl Writeable<'tcx, CtfeProvenance> + 'a)> {
let variants = place.layout().ty.ty_adt_def().unwrap().variants();
let variant_idx = variants
.iter_enumerated()
.find(|(_idx, var)| var.name == name)
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
.0;

interp_ok((variant_idx, self.project_downcast(place, variant_idx)?))
}

// A general method to write an array to a static slice place.
fn allocate_fill_and_write_slice_ptr(
&mut self,
Expand Down Expand Up @@ -83,7 +67,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
let variant_index = match ty.kind() {
ty::Tuple(fields) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Tuple)?;
self.project_downcast_named(&field_dest, sym::Tuple)?;
// project to the single tuple variant field of `type_info::Tuple` struct type
let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
assert_eq!(
Expand All @@ -102,7 +86,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::Array(ty, len) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Array)?;
self.project_downcast_named(&field_dest, sym::Array)?;
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;

self.write_array_type_info(array_place, *ty, *len)?;
Expand All @@ -111,7 +95,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::Slice(ty) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Slice)?;
self.project_downcast_named(&field_dest, sym::Slice)?;
let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?;

self.write_slice_type_info(slice_place, *ty)?;
Expand All @@ -123,16 +107,17 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::Bool => {
let (variant, _variant_place) =
self.downcast(&field_dest, sym::Bool)?;
self.project_downcast_named(&field_dest, sym::Bool)?;
variant
}
ty::Char => {
let (variant, _variant_place) =
self.downcast(&field_dest, sym::Char)?;
self.project_downcast_named(&field_dest, sym::Char)?;
variant
}
ty::Int(int_ty) => {
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
let (variant, variant_place) =
self.project_downcast_named(&field_dest, sym::Int)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_int_type_info(
place,
Expand All @@ -142,7 +127,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
variant
}
ty::Uint(uint_ty) => {
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
let (variant, variant_place) =
self.project_downcast_named(&field_dest, sym::Int)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_int_type_info(
place,
Expand All @@ -153,18 +139,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::Float(float_ty) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Float)?;
self.project_downcast_named(&field_dest, sym::Float)?;
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_float_type_info(place, float_ty.bit_width())?;
variant
}
ty::Str => {
let (variant, _variant_place) = self.downcast(&field_dest, sym::Str)?;
let (variant, _variant_place) =
self.project_downcast_named(&field_dest, sym::Str)?;
variant
}
ty::Ref(_, ty, mutability) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Reference)?;
self.project_downcast_named(&field_dest, sym::Reference)?;
let reference_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_reference_type_info(reference_place, *ty, *mutability)?;
Expand All @@ -173,7 +160,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::RawPtr(ty, mutability) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::Pointer)?;
self.project_downcast_named(&field_dest, sym::Pointer)?;
let pointer_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;

Expand All @@ -183,14 +170,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
ty::Dynamic(predicates, region) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::DynTrait)?;
self.project_downcast_named(&field_dest, sym::DynTrait)?;
let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?;
variant
}
ty::FnPtr(sig, fn_header) => {
let (variant, variant_place) =
self.downcast(&field_dest, sym::FnPtr)?;
self.project_downcast_named(&field_dest, sym::FnPtr)?;
let fn_ptr_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;

Expand All @@ -214,27 +201,10 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(..)
| ty::Error(_) => self.downcast(&field_dest, sym::Other)?.0,
| ty::Error(_) => self.project_downcast_named(&field_dest, sym::Other)?.0,
};
self.write_discriminant(variant_index, &field_dest)?
}
sym::size => {
let layout = self.layout_of(ty)?;
let variant_index = if layout.is_sized() {
let (variant, variant_place) = self.downcast(&field_dest, sym::Some)?;
let size_field_place =
self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_scalar(
ScalarInt::try_from_target_usize(layout.size.bytes(), self.tcx.tcx)
.unwrap(),
&size_field_place,
)?;
variant
} else {
self.downcast(&field_dest, sym::None)?.0
};
self.write_discriminant(variant_index, &field_dest)?;
}
other => span_bug!(self.tcx.span, "unknown `Type` field {other}"),
}
}
Expand Down Expand Up @@ -433,16 +403,17 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
sym::abi => match fn_sig_kind.abi() {
ExternAbi::C { .. } => {
let (rust_variant, _rust_place) =
self.downcast(&field_place, sym::ExternC)?;
self.project_downcast_named(&field_place, sym::ExternC)?;
self.write_discriminant(rust_variant, &field_place)?;
}
ExternAbi::Rust => {
let (rust_variant, _rust_place) =
self.downcast(&field_place, sym::ExternRust)?;
self.project_downcast_named(&field_place, sym::ExternRust)?;
self.write_discriminant(rust_variant, &field_place)?;
}
other_abi => {
let (variant, variant_place) = self.downcast(&field_place, sym::Named)?;
let (variant, variant_place) =
self.project_downcast_named(&field_place, sym::Named)?;
let str_place = self.allocate_str_dedup(other_abi.as_str())?;
let str_ref = self.mplace_to_imm_ptr(&str_place, None)?;
let payload = self.project_field(&variant_place, FieldIdx::ZERO)?;
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_const_eval/src/const_eval/type_info/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
let (adt_ty, adt_def) = adt;
let variant_idx = match adt_def.adt_kind() {
AdtKind::Struct => {
let (variant, variant_place) = self.downcast(place, sym::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,
Expand All @@ -32,7 +32,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
variant
}
AdtKind::Union => {
let (variant, variant_place) = self.downcast(place, sym::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,
Expand All @@ -42,7 +42,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
variant
}
AdtKind::Enum => {
let (variant, variant_place) = self.downcast(place, sym::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)?;
variant
Expand Down Expand Up @@ -219,13 +219,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
_region: Region<'tcx>,
place: MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?;
let (variant_idx, _) = self.project_downcast_named(&place, sym::Lifetime)?;
self.write_discriminant(variant_idx, &place)?;
interp_ok(())
}

fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?;
let (variant_idx, variant_place) = self.project_downcast_named(&place, sym::Type)?;
let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?;

for (field_idx, field_def) in generic_type_place
Expand All @@ -251,7 +251,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") };

let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?;
let (variant_idx, variant_place) = self.project_downcast_named(&place, sym::Const)?;
let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?;

for (field_idx, field_def) in const_place
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_abi::{self as abi, FieldIdx, Size, VariantIdx};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, mir, span_bug, ty};
use rustc_span::Symbol;
use tracing::{debug, instrument};

use super::{
Expand Down Expand Up @@ -227,6 +228,22 @@ where
base.offset(Size::ZERO, layout, self)
}

/// Equivalent to `project_downcast`, but identifies the variant by name instead of index.
pub fn project_downcast_named<P: Projectable<'tcx, M::Provenance>>(
&self,
base: &P,
name: Symbol,
) -> InterpResult<'tcx, (VariantIdx, P)> {
let variants = base.layout().ty.ty_adt_def().unwrap().variants();
let variant_idx = variants
.iter_enumerated()
.find(|(_idx, var)| var.name == name)
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
.0;

interp_ok((variant_idx, self.project_downcast(base, variant_idx)?))
}

/// Compute the offset and field layout for accessing the given index.
pub fn project_index<P: Projectable<'tcx, M::Provenance>>(
&self,
Expand Down
24 changes: 7 additions & 17 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::sinf64
| sym::sinf128
| sym::size_of
| sym::size_of_type_id
| sym::sqrtf16
| sym::sqrtf32
| sym::sqrtf64
Expand Down Expand Up @@ -281,6 +282,7 @@ pub(crate) fn check_intrinsic_type(
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]).skip_norm_wip();
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
};
let type_id_ty = || tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap();

let safety = intrinsic_operation_unsafety(tcx, intrinsic_id);
let n_lts = 0;
Expand All @@ -294,6 +296,7 @@ pub(crate) fn check_intrinsic_type(
sym::size_of_val | sym::align_of_val => {
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize)
}
sym::size_of_type_id => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)),
sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize),
sym::field_offset => (1, 0, vec![], tcx.types.usize),
sym::rustc_peek => (1, 0, vec![param(0)], param(0)),
Expand All @@ -313,16 +316,8 @@ pub(crate) fn check_intrinsic_type(
sym::needs_drop => (1, 0, vec![], tcx.types.bool),

sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
sym::type_id => (
1,
0,
vec![],
tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(),
),
sym::type_id_eq => {
let type_id = tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap();
(0, 0, vec![type_id, type_id], tcx.types.bool)
}
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_vtable => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span);
let dyn_metadata_adt_ref = tcx.adt_def(dyn_metadata);
Expand All @@ -335,17 +330,12 @@ pub(crate) fn check_intrinsic_type(
let option_args = tcx.mk_args(&[dyn_ty.into()]);
let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);

(
0,
0,
vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(); 2],
ret_ty,
)
(0, 0, vec![type_id_ty(); 2], ret_ty)
}
sym::type_of => (
0,
0,
vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap()],
vec![type_id_ty()],
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
),
sym::offload => (
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,7 @@ symbols! {
sinf128,
size,
size_of,
size_of_type_id,
size_of_val,
sized,
sized_hierarchy,
Expand Down
Loading
Loading