]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_const_eval/src/util/alignment.rs
rename Unevaluated to UnevaluatedConst
[rust.git] / compiler / rustc_const_eval / src / util / alignment.rs
1 use rustc_middle::mir::*;
2 use rustc_middle::ty::{self, TyCtxt};
3 use rustc_target::abi::Align;
4
5 /// Returns `true` if this place is allowed to be less aligned
6 /// than its containing struct (because it is within a packed
7 /// struct).
8 pub fn is_disaligned<'tcx, L>(
9     tcx: TyCtxt<'tcx>,
10     local_decls: &L,
11     param_env: ty::ParamEnv<'tcx>,
12     place: Place<'tcx>,
13 ) -> bool
14 where
15     L: HasLocalDecls<'tcx>,
16 {
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);
20         return false;
21     };
22
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.
28             debug!(
29                 "is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
30                 place,
31                 layout.align.abi.bytes(),
32                 pack.bytes()
33             );
34             false
35         }
36         _ => {
37             debug!("is_disaligned({:?}) - true", place);
38             true
39         }
40     }
41 }
42
43 fn is_within_packed<'tcx, L>(
44     tcx: TyCtxt<'tcx>,
45     local_decls: &L,
46     place: Place<'tcx>,
47 ) -> Option<Align>
48 where
49     L: HasLocalDecls<'tcx>,
50 {
51     place
52         .iter_projections()
53         .rev()
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)
59         })
60         // ... and compute their minimum.
61         // The overall smallest alignment is what matters.
62         .min()
63 }