Skip to content

Update InterpCx::project_field to take FieldIdx #142103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 7, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 9 additions & 2 deletions compiler/rustc_abi/src/layout/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ rustc_index::newtype_index! {
pub struct FieldIdx {}
}

impl FieldIdx {
/// The second field.
///
/// For use alongside [`FieldIdx::ZERO`], particularly with scalar pairs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not defined near FieldIdx::ZERO?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because all rustc_newtype_index! types get a ZERO; it's not something special for FieldIdx.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add a const ONE = 1; in the macro to get it generated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That generates it as a non-associated constant, though -- like the START_BLOCK mentioned -- not an associated one. And because ZERO is associated, I wanted ONE to be associated as well.

pub const ONE: FieldIdx = FieldIdx::from_u32(1);
}

rustc_index::newtype_index! {
/// The *source-order* index of a variant in a type.
///
Expand Down Expand Up @@ -274,7 +281,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {

/// Finds the one field that is not a 1-ZST.
/// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(usize, Self)>
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
where
Ty: TyAbiInterface<'a, C> + Copy,
{
Expand All @@ -288,7 +295,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
// More than one non-1-ZST field.
return None;
}
found = Some((field_idx, field));
found = Some((FieldIdx::from_usize(field_idx), field));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may be worth adding an iter and an iter_enumerated method to FieldsShape

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, most of the layout-related usizes in ABI are sketchy. I've tried pulling on the tendrils before, but usually ended up giving up because of just how far that goes and -- as I mentioned in the other PR -- that the ones related to arrays sometimes need more than FieldIdx, and figuring out which those are can be hard.

(Conveniently this one was obvious because a over-4-billion-length array clearly can't have exactly one non-ZST.)

}
found
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<ty
// Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
let ty = fields[FieldIdx::ONE].ty(fx.tcx, args);
let ty::Adt(ty, args) = ty.kind() else {
unreachable!("expected first field of `MaybeUninit` to be an ADT")
};
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_codegen_cranelift/src/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
.layout()
.non_1zst_field(fx)
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
arg = arg.value_field(fx, FieldIdx::new(idx));
arg = arg.value_field(fx, idx);
}
}

Expand All @@ -62,8 +62,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
let vtable =
dyn_star.place_field(fx, FieldIdx::new(1)).to_cvalue(fx).load_scalar(fx);
let vtable = dyn_star.place_field(fx, FieldIdx::ONE).to_cvalue(fx).load_scalar(fx);
break 'block (ptr, vtable);
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let (idx, _) = op.layout.non_1zst_field(bx).expect(
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
);
op = op.extract_field(self, bx, idx);
op = op.extract_field(self, bx, idx.as_usize());
}

// Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
Expand Down Expand Up @@ -1109,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let (idx, _) = op.layout.non_1zst_field(bx).expect(
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
);
op = op.extract_field(self, bx, idx);
op = op.extract_field(self, bx, idx.as_usize());
}

// Make sure that we've actually unwrapped the rcvr down
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Not in interpret to make sure we do not use private implementation details

use rustc_abi::VariantIdx;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_middle::query::Key;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
Expand Down Expand Up @@ -60,7 +60,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(

let fields_iter = (0..field_count)
.map(|i| {
let field_op = ecx.project_field(&down, i).discard_err()?;
let field_op = ecx.project_field(&down, FieldIdx::from_usize(i)).discard_err()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also use a typed field iterator

let val = op_to_const(&ecx, &field_op, /* for diagnostics */ true);
Some((val, field_op.layout.ty))
})
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_abi::{BackendRepr, VariantIdx};
use rustc_abi::{BackendRepr, FieldIdx, VariantIdx};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ReportedErrorInfo};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
Expand Down Expand Up @@ -40,7 +40,7 @@ fn branches<'tcx>(
}

for i in 0..field_count {
let field = ecx.project_field(&place, i).unwrap();
let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap();
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And more here

(probably not worth pointing them all out)

branches.push(valtree);
}
Expand Down Expand Up @@ -437,7 +437,7 @@ fn valtree_into_mplace<'tcx>(
ty::Str | ty::Slice(_) | ty::Array(..) => {
ecx.project_index(place, i as u64).unwrap()
}
_ => ecx.project_field(&place_adjusted, i).unwrap(),
_ => ecx.project_field(&place_adjusted, FieldIdx::from_usize(i)).unwrap(),
};

debug!(?place_inner);
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub(super) fn fn_arg_field(
&self,
arg: &FnArg<'tcx, M::Provenance>,
field: usize,
field: FieldIdx,
) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
interp_ok(match arg {
FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
Expand Down Expand Up @@ -600,10 +600,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
Cow::from(
args.iter()
.map(|a| interp_ok(a.clone()))
.chain(
(0..untuple_arg.layout().fields.count())
.map(|i| self.fn_arg_field(untuple_arg, i)),
)
.chain((0..untuple_arg.layout().fields.count()).map(|i| {
self.fn_arg_field(untuple_arg, FieldIdx::from_usize(i))
}))
.collect::<InterpResult<'_, Vec<_>>>()?,
)
} else {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/cast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::assert_matches::assert_matches;

use rustc_abi::Integer;
use rustc_abi::{FieldIdx, Integer};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::{Float, FloatConvert};
use rustc_middle::mir::CastKind;
Expand Down Expand Up @@ -484,6 +484,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let mut found_cast_field = false;
for i in 0..src.layout.fields.count() {
let cast_ty_field = cast_ty.field(self, i);
let i = FieldIdx::from_usize(i);
let src_field = self.project_field(src, i)?;
let dst_field = self.project_field(dest, i)?;
if src_field.layout.is_1zst() && cast_ty_field.is_1zst() {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// No need to validate that the discriminant here because the
// `TyAndLayout::for_variant()` call earlier already checks the
// variant is valid.
let tag_dest = self.project_field(dest, tag_field.as_usize())?;
let tag_dest = self.project_field(dest, tag_field)?;
self.write_scalar(tag, &tag_dest)
}
None => {
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;

// Read tag and sanity-check `tag_layout`.
let tag_val = self.read_immediate(&self.project_field(op, tag_field.as_usize())?)?;
let tag_val = self.read_immediate(&self.project_field(op, tag_field)?)?;
assert_eq!(tag_layout.size, tag_val.layout.size);
assert_eq!(tag_layout.backend_repr.is_signed(), tag_val.layout.backend_repr.is_signed());
trace!("tag value: {}", tag_val);
Expand Down
18 changes: 9 additions & 9 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use std::marker::PhantomData;
use std::ops::Range;

use rustc_abi::{self as abi, Size, VariantIdx};
use rustc_abi::{self as abi, FieldIdx, Size, VariantIdx};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::{bug, mir, span_bug, ty};
Expand Down Expand Up @@ -144,22 +144,22 @@ where
/// always possible without allocating, so it can take `&self`. Also return the field's layout.
/// This supports both struct and array fields, but not slices!
///
/// This also works for arrays, but then the `usize` index type is restricting.
/// For indexing into arrays, use `mplace_index`.
/// This also works for arrays, but then the `FieldIdx` index type is restricting.
/// For indexing into arrays, use [`Self::project_index`].
pub fn project_field<P: Projectable<'tcx, M::Provenance>>(
&self,
base: &P,
field: usize,
field: FieldIdx,
) -> InterpResult<'tcx, P> {
// Slices nominally have length 0, so they will panic somewhere in `fields.offset`.
debug_assert!(
!matches!(base.layout().ty.kind(), ty::Slice(..)),
"`field` projection called on a slice -- call `index` projection instead"
);
let offset = base.layout().fields.offset(field);
let offset = base.layout().fields.offset(field.as_usize());
// Computing the layout does normalization, so we get a normalized type out of this
// even if the field type is non-normalized (possible e.g. via associated types).
let field_layout = base.layout().field(self, field);
let field_layout = base.layout().field(self, field.as_usize());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does field not take FieldIdx...?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// Offset may need adjustment for unsized fields.
let (meta, offset) = if field_layout.is_unsized() {
Expand Down Expand Up @@ -244,7 +244,7 @@ where
}
_ => span_bug!(
self.cur_span(),
"`mplace_index` called on non-array type {:?}",
"`project_index` called on non-array type {:?}",
base.layout().ty
),
};
Expand All @@ -260,7 +260,7 @@ where
) -> InterpResult<'tcx, (P, u64)> {
assert!(base.layout().ty.ty_adt_def().unwrap().repr().simd());
// SIMD types must be newtypes around arrays, so all we have to do is project to their only field.
let array = self.project_field(base, 0)?;
let array = self.project_field(base, FieldIdx::ZERO)?;
let len = array.len(self)?;
interp_ok((array, len))
}
Expand Down Expand Up @@ -384,7 +384,7 @@ where
UnwrapUnsafeBinder(target) => base.transmute(self.layout_of(target)?, self)?,
// We don't want anything happening here, this is here as a dummy.
Subtype(_) => base.transmute(base.layout(), self)?,
Field(field, _) => self.project_field(base, field.index())?,
Field(field, _) => self.project_field(base, field)?,
Downcast(_, variant) => self.project_downcast(base, variant)?,
Deref => self.deref_pointer(&base.to_op(self)?)?.into(),
Index(local) => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
for (field_index, operand) in operands.iter_enumerated() {
let field_index = active_field_index.unwrap_or(field_index);
let field_dest = self.project_field(&variant_dest, field_index.as_usize())?;
let field_dest = self.project_field(&variant_dest, field_index)?;
let op = self.eval_operand(operand, Some(field_dest.layout))?;
self.copy_op(&op, &field_dest)?;
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/interpret/traits.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_abi::{Align, Size};
use rustc_abi::{Align, FieldIdx, Size};
use rustc_middle::mir::interpret::{InterpResult, Pointer};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry};
Expand Down Expand Up @@ -137,8 +137,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"`unpack_dyn_star` only makes sense on `dyn*` types"
);
let data = self.project_field(val, 0)?;
let vtable = self.project_field(val, 1)?;
let data = self.project_field(val, FieldIdx::ZERO)?;
let vtable = self.project_field(val, FieldIdx::ONE)?;
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
// `data` is already the right thing but has the wrong type. So we transmute it.
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_const_eval/src/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
// So we transmute it to a raw pointer.
let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
let vtable_field =
self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?;
let vtable_field = self
.ecx()
.project_field(v, FieldIdx::ONE)?
.transmute(raw_ptr_ty, self.ecx())?;
self.visit_field(v, 1, &vtable_field)?;

// Then unpack the first field, and continue.
Expand All @@ -140,14 +142,16 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {

// `Box` has two fields: the pointer we care about, and the allocator.
assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields");
let (unique_ptr, alloc) =
(self.ecx().project_field(v, 0)?, self.ecx().project_field(v, 1)?);
let (unique_ptr, alloc) = (
self.ecx().project_field(v, FieldIdx::ZERO)?,
self.ecx().project_field(v, FieldIdx::ONE)?,
);
// Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`...
// (which means another 2 fields, the second of which is a `PhantomData`)
assert_eq!(unique_ptr.layout().fields.count(), 2);
let (nonnull_ptr, phantom) = (
self.ecx().project_field(&unique_ptr, 0)?,
self.ecx().project_field(&unique_ptr, 1)?,
self.ecx().project_field(&unique_ptr, FieldIdx::ZERO)?,
self.ecx().project_field(&unique_ptr, FieldIdx::ONE)?,
);
assert!(
phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()),
Expand All @@ -156,7 +160,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
);
// ... that contains a `NonNull`... (gladly, only a single field here)
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
// ... whose only field finally is a raw ptr we can dereference.
self.visit_box(ty, &raw_ptr)?;

Expand Down Expand Up @@ -188,9 +192,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
}
FieldsShape::Arbitrary { memory_index, .. } => {
for idx in Self::aggregate_field_iter(memory_index) {
let idx = idx.as_usize();
let field = self.ecx().project_field(v, idx)?;
self.visit_field(v, idx, &field)?;
self.visit_field(v, idx.as_usize(), &field)?;
}
}
FieldsShape::Array { .. } => {
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_const_eval/src/util/caller_location.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_abi::FieldIdx;
use rustc_hir::LangItem;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, TyCtxt};
Expand Down Expand Up @@ -41,11 +42,14 @@ fn alloc_caller_location<'tcx>(
let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();

// Initialize fields.
ecx.write_immediate(file_wide_ptr, &ecx.project_field(&location, 0).unwrap())
ecx.write_immediate(
file_wide_ptr,
&ecx.project_field(&location, FieldIdx::from_u32(0)).unwrap(),
)
.expect("writing to memory we just allocated cannot fail");
ecx.write_scalar(line, &ecx.project_field(&location, FieldIdx::from_u32(1)).unwrap())
.expect("writing to memory we just allocated cannot fail");
ecx.write_scalar(line, &ecx.project_field(&location, 1).unwrap())
.expect("writing to memory we just allocated cannot fail");
ecx.write_scalar(col, &ecx.project_field(&location, 2).unwrap())
ecx.write_scalar(col, &ecx.project_field(&location, FieldIdx::from_u32(2)).unwrap())
.expect("writing to memory we just allocated cannot fail");

location
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
return;
};

if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
if let Some(second_field) = fields.get(FieldIdx::ONE) {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
.with_span_label(tcx.def_span(second_field.did), "excess field")
.emit();
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
_ if ty.references_error() => return None,
ty::Adt(adt, args) if self.tcx().is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx(), args);
let ty = fields[FieldIdx::ONE].ty(self.tcx(), args);
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
// If so, just get it from the args.
let ty::Adt(ty, args) = ty.kind() else {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_mir_transform/src/dataflow_const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
place,
operand,
&mut |elem, op| match elem {
TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).discard_err(),
TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(),
TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(),
TrackElem::Discriminant => {
let variant = self.ecx.read_discriminant(op).discard_err()?;
Expand Down Expand Up @@ -890,7 +890,8 @@ fn try_write_constant<'tcx>(

ty::Tuple(elem_tys) => {
for (i, elem) in elem_tys.iter().enumerate() {
let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else {
let i = FieldIdx::from_usize(i);
let Some(field) = map.apply(place, TrackElem::Field(i)) else {
throw_machine_stop_str!("missing field in tuple")
};
let field_dest = ecx.project_field(dest, i)?;
Expand Down Expand Up @@ -928,7 +929,7 @@ fn try_write_constant<'tcx>(
let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else {
throw_machine_stop_str!("missing field in ADT")
};
let field_dest = ecx.project_field(&variant_dest, i.as_usize())?;
let field_dest = ecx.project_field(&variant_dest, i)?;
try_write_constant(ecx, &field_dest, field, ty, state, map)?;
}
ecx.write_discriminant(variant_idx, dest)?;
Expand Down
Loading
Loading