diff options
| author | Lukas Markeffsky <@> | 2023-07-02 14:07:08 +0200 |
|---|---|---|
| committer | Lukas Markeffsky <@> | 2023-07-06 13:15:05 +0000 |
| commit | e3de14e46396694e48bfecf963fe9fa8e8a90d86 (patch) | |
| tree | c7e9984848e1e425f398e113c42b92decedaa816 /compiler/rustc_ty_utils/src | |
| parent | 478071ba9daabcdbc880db5638989dc16545537c (diff) | |
| download | rust-e3de14e46396694e48bfecf963fe9fa8e8a90d86.tar.gz rust-e3de14e46396694e48bfecf963fe9fa8e8a90d86.zip | |
sanity check field offsets in unsizeable structs
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f6bc0dc330d..0dbe6265522 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -499,6 +499,55 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::SizeOverflow(ty))); }; + // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. + if cfg!(debug_assertions) + && maybe_unsized + && def + .non_enum_variant() + .fields + .raw + .last() + .unwrap() + .ty(tcx, substs) + .is_sized(tcx, cx.param_env) + { + let mut variants = variants; + let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); + *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement.layout; + + let Some(unsized_layout) = cx.layout_of_struct_or_enum( + &def.repr(), + &variants, + def.is_enum(), + def.is_unsafe_cell(), + tcx.layout_scalar_valid_range(def.did()), + get_discriminant_type, + discriminants_iter(), + dont_niche_optimize_enum, + !maybe_unsized, + ) else { + bug!("failed to compute unsized layout of {ty:?}"); + }; + + let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else { + bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields); + }; + let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else { + bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields); + }; + + let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap(); + let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap(); + + if sized_fields != unsized_fields { + bug!("unsizing {ty:?} changed field order!\n{layout:?}\n{unsized_layout:?}"); + } + + if sized_tail < unsized_tail { + bug!("unsizing {ty:?} moved tail backwards!\n{layout:?}\n{unsized_layout:?}"); + } + } + tcx.mk_layout(layout) } |
