1 use rustc_middle::mir::*;
2 use rustc_middle::ty::{self, TyCtxt};
3 use rustc_target::abi::Align;
5 /// Returns `true` if this place is allowed to be less aligned
6 /// than its containing struct (because it is within a packed
8 pub fn is_disaligned<'tcx, L>(
11 param_env: ty::ParamEnv<'tcx>,
15 L: HasLocalDecls<'tcx>,
17 debug!("is_disaligned({:?})", place);
18 let Some(pack) = is_within_packed(tcx, local_decls, place) else {
19 debug!("is_disaligned({:?}) - not within packed", place);
23 let ty = place.ty(local_decls, tcx).ty;
24 match tcx.layout_of(param_env.and(ty)) {
25 Ok(layout) if layout.align.abi <= pack => {
26 // If the packed alignment is greater or equal to the field alignment, the type won't be
27 // further disaligned.
29 "is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
31 layout.align.abi.bytes(),
37 debug!("is_disaligned({:?}) - true", place);
43 fn is_within_packed<'tcx, L>(
49 L: HasLocalDecls<'tcx>,
54 // Stop at `Deref`; standard ABI alignment applies there.
55 .take_while(|(_base, elem)| !matches!(elem, ProjectionElem::Deref))
56 // Consider the packed alignments at play here...
57 .filter_map(|(base, _elem)| {
58 base.ty(local_decls, tcx).ty.ty_adt_def().and_then(|adt| adt.repr().pack)
60 // ... and compute their minimum.
61 // The overall smallest alignment is what matters.