Rollup merge of #115798 - RalfJung:non_1zst_field, r=wesleywiser
add helper method for finding the one non-1-ZST field
This commit is contained in:
commit
565b9c2264
@ -48,19 +48,12 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
|||||||
) -> (Pointer, Value) {
|
) -> (Pointer, Value) {
|
||||||
let (ptr, vtable) = 'block: {
|
let (ptr, vtable) = 'block: {
|
||||||
if let Abi::Scalar(_) = arg.layout().abi {
|
if let Abi::Scalar(_) = arg.layout().abi {
|
||||||
'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() {
|
while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() {
|
||||||
for i in 0..arg.layout().fields.count() {
|
let (idx, _) = arg
|
||||||
let field = arg.value_field(fx, FieldIdx::new(i));
|
.layout()
|
||||||
if !field.layout().is_1zst() {
|
.non_1zst_field(fx)
|
||||||
// we found the one non-1-ZST field that is allowed
|
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
|
||||||
// now find *its* non-zero-sized field, or stop if it's a
|
arg = arg.value_field(fx, FieldIdx::new(idx));
|
||||||
// pointer
|
|
||||||
arg = field;
|
|
||||||
continue 'descend_newtypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bug!("receiver has no non-zero-sized fields {:?}", arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,21 +928,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
// we get a value of a built-in pointer type.
|
// we get a value of a built-in pointer type.
|
||||||
//
|
//
|
||||||
// This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`.
|
// This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`.
|
||||||
'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
|
while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_ref() {
|
||||||
&& !op.layout.ty.is_ref()
|
let (idx, _) = op.layout.non_1zst_field(bx).expect(
|
||||||
{
|
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||||
for i in 0..op.layout.fields.count() {
|
);
|
||||||
let field = op.extract_field(bx, i);
|
op = op.extract_field(bx, idx);
|
||||||
if !field.layout.is_1zst() {
|
|
||||||
// we found the one non-1-ZST field that is allowed
|
|
||||||
// now find *its* non-zero-sized field, or stop if it's a
|
|
||||||
// pointer
|
|
||||||
op = field;
|
|
||||||
continue 'descend_newtypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
|
// now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
|
||||||
@ -970,22 +960,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
Immediate(_) => {
|
Immediate(_) => {
|
||||||
// See comment above explaining why we peel these newtypes
|
// See comment above explaining why we peel these newtypes
|
||||||
'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
|
while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_ref() {
|
||||||
&& !op.layout.ty.is_ref()
|
let (idx, _) = op.layout.non_1zst_field(bx).expect(
|
||||||
{
|
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||||
for i in 0..op.layout.fields.count() {
|
);
|
||||||
let field = op.extract_field(bx, i);
|
op = op.extract_field(bx, idx);
|
||||||
if !field.layout.is_1zst() {
|
|
||||||
// We found the one non-1-ZST field that is allowed. (The rules
|
|
||||||
// for `DispatchFromDyn` ensure there's exactly one such field.)
|
|
||||||
// Now find *its* non-zero-sized field, or stop if it's a
|
|
||||||
// pointer.
|
|
||||||
op = field;
|
|
||||||
continue 'descend_newtypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that we've actually unwrapped the rcvr down
|
// Make sure that we've actually unwrapped the rcvr down
|
||||||
|
@ -269,19 +269,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
match layout.ty.kind() {
|
match layout.ty.kind() {
|
||||||
ty::Adt(adt_def, _) if adt_def.repr().transparent() && may_unfold(*adt_def) => {
|
ty::Adt(adt_def, _) if adt_def.repr().transparent() && may_unfold(*adt_def) => {
|
||||||
assert!(!adt_def.is_enum());
|
assert!(!adt_def.is_enum());
|
||||||
// Find the non-1-ZST field.
|
// Find the non-1-ZST field, and recurse.
|
||||||
let mut non_1zst_fields = (0..layout.fields.count()).filter_map(|idx| {
|
let (_, field) = layout.non_1zst_field(self).unwrap();
|
||||||
let field = layout.field(self, idx);
|
self.unfold_transparent(field, may_unfold)
|
||||||
if field.is_1zst() { None } else { Some(field) }
|
|
||||||
});
|
|
||||||
let first = non_1zst_fields.next().expect("`unfold_transparent` called on 1-ZST");
|
|
||||||
assert!(
|
|
||||||
non_1zst_fields.next().is_none(),
|
|
||||||
"more than one non-1-ZST field in a transparent type"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Found it!
|
|
||||||
self.unfold_transparent(first, may_unfold)
|
|
||||||
}
|
}
|
||||||
// Not a transparent type, no further unfolding.
|
// Not a transparent type, no further unfolding.
|
||||||
_ => layout,
|
_ => layout,
|
||||||
@ -797,25 +787,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
_ => {
|
_ => {
|
||||||
// Not there yet, search for the only non-ZST field.
|
// Not there yet, search for the only non-ZST field.
|
||||||
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
|
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
|
||||||
let mut non_zst_field = None;
|
let (idx, _) = receiver.layout.non_1zst_field(self).expect(
|
||||||
for i in 0..receiver.layout.fields.count() {
|
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||||
let field = self.project_field(&receiver, i)?;
|
);
|
||||||
let zst = field.layout.is_1zst();
|
receiver = self.project_field(&receiver, idx)?;
|
||||||
if !zst {
|
|
||||||
assert!(
|
|
||||||
non_zst_field.is_none(),
|
|
||||||
"multiple non-1-ZST fields in dyn receiver type {}",
|
|
||||||
receiver.layout.ty
|
|
||||||
);
|
|
||||||
non_zst_field = Some(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
receiver = non_zst_field.unwrap_or_else(|| {
|
|
||||||
panic!(
|
|
||||||
"no non-1-ZST fields in dyn receiver type {}",
|
|
||||||
receiver.layout.ty
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -144,4 +144,25 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||||||
|
|
||||||
offset
|
offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)>
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
|
{
|
||||||
|
let mut found = None;
|
||||||
|
for field_idx in 0..self.fields.count() {
|
||||||
|
let field = self.field(cx, field_idx);
|
||||||
|
if field.is_1zst() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if found.is_some() {
|
||||||
|
// More than one non-1-ZST field.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
found = Some((field_idx, field));
|
||||||
|
}
|
||||||
|
found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,19 +588,11 @@ fn make_thin_self_ptr<'tcx>(
|
|||||||
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
||||||
// get a built-in pointer type
|
// get a built-in pointer type
|
||||||
let mut fat_pointer_layout = layout;
|
let mut fat_pointer_layout = layout;
|
||||||
'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
|
while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() {
|
||||||
&& !fat_pointer_layout.ty.is_ref()
|
fat_pointer_layout = fat_pointer_layout
|
||||||
{
|
.non_1zst_field(cx)
|
||||||
for i in 0..fat_pointer_layout.fields.count() {
|
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
||||||
let field_layout = fat_pointer_layout.field(cx, i);
|
.1
|
||||||
|
|
||||||
if !field_layout.is_1zst() {
|
|
||||||
fat_pointer_layout = field_layout;
|
|
||||||
continue 'descend_newtypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bug!("receiver has no non-1-ZST fields {:?}", fat_pointer_layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fat_pointer_layout.ty
|
fat_pointer_layout.ty
|
||||||
|
Loading…
x
Reference in New Issue
Block a user