const_eval and codegen: audit uses of is_zst
This commit is contained in:
parent
bf91321e0f
commit
b2ebf1c23f
12 changed files with 42 additions and 29 deletions
|
@ -410,21 +410,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.unsize_into_ptr(src, dest, *s, *c)
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
assert_eq!(def_a, def_b); // implies same number of fields
|
||||
|
||||
// unsizing of generic struct with pointer fields
|
||||
// Example: `Arc<T>` -> `Arc<Trait>`
|
||||
// here we need to increase the size of every &T thin ptr field to a fat ptr
|
||||
// Unsizing of generic struct with pointer fields, like `Arc<T>` -> `Arc<Trait>`.
|
||||
// There can be extra fields as long as they don't change their type or are 1-ZST.
|
||||
// There might also be no field that actually needs unsizing.
|
||||
let mut found_cast_field = false;
|
||||
for i in 0..src.layout.fields.count() {
|
||||
let cast_ty_field = cast_ty.field(self, i);
|
||||
if cast_ty_field.is_zst() {
|
||||
continue;
|
||||
}
|
||||
let src_field = self.project_field(src, i)?;
|
||||
let dst_field = self.project_field(dest, i)?;
|
||||
if src_field.layout.ty == cast_ty_field.ty {
|
||||
if src_field.layout.is_1zst() && cast_ty_field.is_1zst() {
|
||||
// Skip 1-ZST fields.
|
||||
} else if src_field.layout.ty == cast_ty_field.ty {
|
||||
self.copy_op(&src_field, &dst_field, /*allow_transmute*/ false)?;
|
||||
} else {
|
||||
if found_cast_field {
|
||||
span_bug!(self.cur_span(), "unsize_into: more than one field to cast");
|
||||
}
|
||||
found_cast_field = true;
|
||||
self.unsize_into(&src_field, cast_ty_field, &dst_field)?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,6 +239,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
|
|||
// if the entire value is uninit, then so is the field (can happen in ConstProp)
|
||||
(Immediate::Uninit, _) => Immediate::Uninit,
|
||||
// the field contains no information, can be left uninit
|
||||
// (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
|
||||
_ if layout.is_zst() => Immediate::Uninit,
|
||||
// some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try
|
||||
// to detect those here and also give them no data
|
||||
|
|
|
@ -684,15 +684,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
_ => {
|
||||
// Not there yet, search for the only non-ZST field.
|
||||
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
|
||||
let mut non_zst_field = None;
|
||||
for i in 0..receiver.layout.fields.count() {
|
||||
let field = self.project_field(&receiver, i)?;
|
||||
let zst =
|
||||
field.layout.is_zst() && field.layout.align.abi.bytes() == 1;
|
||||
let zst = field.layout.is_1zst();
|
||||
if !zst {
|
||||
assert!(
|
||||
non_zst_field.is_none(),
|
||||
"multiple non-ZST fields in dyn receiver type {}",
|
||||
"multiple non-1-ZST fields in dyn receiver type {}",
|
||||
receiver.layout.ty
|
||||
);
|
||||
non_zst_field = Some(field);
|
||||
|
@ -700,7 +700,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
receiver = non_zst_field.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"no non-ZST fields in dyn receiver type {}",
|
||||
"no non-1-ZST fields in dyn receiver type {}",
|
||||
receiver.layout.ty
|
||||
)
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue