Skip to content

Commit bf2f8ff

Browse files
committed
Move naive_layout_of query provider in separate sibling module
1 parent 8e28729 commit bf2f8ff

File tree

4 files changed

+253
-230
lines changed

4 files changed

+253
-230
lines changed

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 5 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use rustc_index::{IndexSlice, IndexVec};
55
use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
66
use rustc_middle::query::{LocalCrate, Providers};
77
use rustc_middle::ty::layout::{
8-
IntegerExt, LayoutCx, LayoutError, LayoutOf, NaiveAbi, NaiveLayout, TyAndLayout,
9-
TyAndNaiveLayout, MAX_SIMD_LANES,
8+
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
109
};
1110
use rustc_middle::ty::{
1211
self, AdtDef, EarlyBinder, GenericArgsRef, ReprOptions, Ty, TyCtxt, TypeVisitableExt,
@@ -25,7 +24,7 @@ use crate::errors::{
2524
use crate::layout_sanity_check::sanity_check_layout;
2625

2726
pub fn provide(providers: &mut Providers) {
28-
*providers = Providers { layout_of, naive_layout_of, reference_niches_policy, ..*providers };
27+
*providers = Providers { layout_of, reference_niches_policy, ..*providers };
2928
}
3029

3130
#[instrument(skip(tcx), level = "debug")]
@@ -37,40 +36,6 @@ fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceN
3736
/// crates not specifying `-Z reference-niches`.
3837
const DEFAULT_REF_NICHES: ReferenceNichePolicy = ReferenceNichePolicy { size: false, align: false };
3938

40-
#[instrument(skip(tcx, query), level = "debug")]
41-
fn naive_layout_of<'tcx>(
42-
tcx: TyCtxt<'tcx>,
43-
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
44-
) -> Result<TyAndNaiveLayout<'tcx>, &'tcx LayoutError<'tcx>> {
45-
let (param_env, ty) = query.into_parts();
46-
debug!(?ty);
47-
48-
let param_env = param_env.with_reveal_all_normalized(tcx);
49-
let unnormalized_ty = ty;
50-
51-
// FIXME: We might want to have two different versions of `layout_of`:
52-
// One that can be called after typecheck has completed and can use
53-
// `normalize_erasing_regions` here and another one that can be called
54-
// before typecheck has completed and uses `try_normalize_erasing_regions`.
55-
let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
56-
Ok(t) => t,
57-
Err(normalization_error) => {
58-
return Err(tcx
59-
.arena
60-
.alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
61-
}
62-
};
63-
64-
if ty != unnormalized_ty {
65-
// Ensure this layout is also cached for the normalized type.
66-
return tcx.naive_layout_of(param_env.and(ty));
67-
}
68-
69-
let cx = LayoutCx { tcx, param_env };
70-
let layout = naive_layout_of_uncached(&cx, ty)?;
71-
Ok(TyAndNaiveLayout { ty, layout })
72-
}
73-
7439
#[instrument(skip(tcx, query), level = "debug")]
7540
fn layout_of<'tcx>(
7641
tcx: TyCtxt<'tcx>,
@@ -90,13 +55,9 @@ fn layout_of<'tcx>(
9055
let cx = LayoutCx { tcx, param_env };
9156
let layout = layout_of_uncached(&cx, ty)?;
9257

93-
if !naive.is_refined_by(layout) {
94-
bug!("the naive layout isn't refined by the actual layout:\n{:#?}\n{:#?}", naive, layout,);
95-
}
96-
9758
let layout = TyAndLayout { ty, layout };
9859
record_layout_for_printing(&cx, layout);
99-
sanity_check_layout(&cx, &layout);
60+
sanity_check_layout(&cx, &layout, &naive);
10061

10162
Ok(layout)
10263
}
@@ -108,191 +69,6 @@ fn error<'tcx>(
10869
cx.tcx.arena.alloc(err)
10970
}
11071

111-
fn naive_layout_of_uncached<'tcx>(
112-
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
113-
ty: Ty<'tcx>,
114-
) -> Result<NaiveLayout, &'tcx LayoutError<'tcx>> {
115-
let tcx = cx.tcx;
116-
let dl = cx.data_layout();
117-
118-
let scalar = |value: Primitive| NaiveLayout {
119-
abi: NaiveAbi::Scalar(value),
120-
size: value.size(dl),
121-
align: value.align(dl).abi,
122-
exact: true,
123-
};
124-
125-
let univariant = |fields: &mut dyn Iterator<Item = Ty<'tcx>>,
126-
repr: &ReprOptions|
127-
-> Result<NaiveLayout, &'tcx LayoutError<'tcx>> {
128-
if repr.pack.is_some() && repr.align.is_some() {
129-
cx.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
130-
return Err(error(cx, LayoutError::Unknown(ty)));
131-
}
132-
133-
let linear = repr.inhibit_struct_field_reordering_opt();
134-
let pack = repr.pack.unwrap_or(Align::MAX);
135-
let mut layout = NaiveLayout::EMPTY;
136-
137-
for field in fields {
138-
let field = cx.naive_layout_of(field)?.packed(pack);
139-
if linear {
140-
layout = layout.pad_to_align(field.align);
141-
}
142-
layout = layout
143-
.concat(&field, dl)
144-
.ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
145-
}
146-
147-
if let Some(align) = repr.align {
148-
layout = layout.align_to(align);
149-
}
150-
151-
if linear {
152-
layout.abi = layout.abi.as_aggregate();
153-
}
154-
155-
Ok(layout.pad_to_align(layout.align))
156-
};
157-
158-
debug_assert!(!ty.has_non_region_infer());
159-
160-
Ok(match *ty.kind() {
161-
// Basic scalars
162-
ty::Bool => scalar(Int(I8, false)),
163-
ty::Char => scalar(Int(I32, false)),
164-
ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
165-
ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
166-
ty::Float(fty) => scalar(match fty {
167-
ty::FloatTy::F32 => F32,
168-
ty::FloatTy::F64 => F64,
169-
}),
170-
ty::FnPtr(_) => scalar(Pointer(dl.instruction_address_space)),
171-
172-
// The never type.
173-
ty::Never => NaiveLayout { abi: NaiveAbi::Uninhabited, ..NaiveLayout::EMPTY },
174-
175-
// Potentially-wide pointers.
176-
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
177-
let data_ptr = scalar(Pointer(AddressSpace::DATA));
178-
if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
179-
// Effectively a (ptr, meta) tuple.
180-
let l = data_ptr
181-
.concat(&scalar(metadata.primitive()), dl)
182-
.ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
183-
l.pad_to_align(l.align)
184-
} else {
185-
// No metadata, this is a thin pointer.
186-
data_ptr
187-
}
188-
}
189-
190-
ty::Dynamic(_, _, ty::DynStar) => {
191-
let ptr = scalar(Pointer(AddressSpace::DATA));
192-
ptr.concat(&ptr, dl).ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?
193-
}
194-
195-
// Arrays and slices.
196-
ty::Array(element, count) => {
197-
let count = compute_array_count(cx, count)
198-
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
199-
let element = cx.naive_layout_of(element)?;
200-
NaiveLayout {
201-
abi: element.abi.as_aggregate(),
202-
size: element
203-
.size
204-
.checked_mul(count, cx)
205-
.ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?,
206-
..*element
207-
}
208-
}
209-
ty::Slice(element) => {
210-
let element = cx.naive_layout_of(element)?;
211-
NaiveLayout { abi: NaiveAbi::Unsized, size: Size::ZERO, ..*element }
212-
}
213-
214-
ty::FnDef(..) => NaiveLayout::EMPTY,
215-
216-
// Unsized types.
217-
ty::Str | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
218-
NaiveLayout { abi: NaiveAbi::Unsized, ..NaiveLayout::EMPTY }
219-
}
220-
221-
// FIXME(reference_niches): try to actually compute a reasonable layout estimate,
222-
// without duplicating too much code from `generator_layout`.
223-
ty::Generator(..) => NaiveLayout { exact: false, ..NaiveLayout::EMPTY },
224-
225-
ty::Closure(_, ref substs) => {
226-
univariant(&mut substs.as_closure().upvar_tys(), &ReprOptions::default())?
227-
}
228-
229-
ty::Tuple(tys) => univariant(&mut tys.iter(), &ReprOptions::default())?,
230-
231-
ty::Adt(def, substs) if def.is_union() => {
232-
let repr = def.repr();
233-
let pack = repr.pack.unwrap_or(Align::MAX);
234-
if repr.pack.is_some() && repr.align.is_some() {
235-
cx.tcx.sess.delay_span_bug(DUMMY_SP, "union cannot be packed and aligned");
236-
return Err(error(cx, LayoutError::Unknown(ty)));
237-
}
238-
239-
let mut layout = NaiveLayout::EMPTY;
240-
for f in &def.variants()[FIRST_VARIANT].fields {
241-
let field = cx.naive_layout_of(f.ty(tcx, substs))?;
242-
layout = layout.union(&field.packed(pack));
243-
}
244-
245-
// Unions are always inhabited, and never scalar if `repr(C)`.
246-
if !matches!(layout.abi, NaiveAbi::Scalar(_)) || repr.inhibit_enum_layout_opt() {
247-
layout.abi = NaiveAbi::Sized;
248-
}
249-
250-
if let Some(align) = repr.align {
251-
layout = layout.align_to(align);
252-
}
253-
layout.pad_to_align(layout.align)
254-
}
255-
256-
ty::Adt(def, substs) => {
257-
let repr = def.repr();
258-
let base = NaiveLayout {
259-
// For simplicity, assume that any enum has its discriminant field (if it exists)
260-
// niched inside one of the variants; this will underestimate the size (and sometimes
261-
// alignment) of enums. We also doesn't compute exact alignment for SIMD structs.
262-
// FIXME(reference_niches): Be smarter here.
263-
// Also consider adding a special case for null-optimized enums, so that we can have
264-
// `Option<&T>: PointerLike` in generic contexts.
265-
exact: !def.is_enum() && !repr.simd(),
266-
// An ADT with no inhabited variants should have an uninhabited ABI.
267-
abi: NaiveAbi::Uninhabited,
268-
..NaiveLayout::EMPTY
269-
};
270-
271-
let layout = def.variants().iter().try_fold(base, |layout, v| {
272-
let mut fields = v.fields.iter().map(|f| f.ty(tcx, substs));
273-
let vlayout = univariant(&mut fields, &repr)?;
274-
Ok(layout.union(&vlayout))
275-
})?;
276-
layout.pad_to_align(layout.align)
277-
}
278-
279-
// Types with no meaningful known layout.
280-
ty::Alias(..) => {
281-
// NOTE(eddyb) `layout_of` query should've normalized these away,
282-
// if that was possible, so there's no reason to try again here.
283-
return Err(error(cx, LayoutError::Unknown(ty)));
284-
}
285-
286-
ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
287-
bug!("Layout::compute: unexpected type `{}`", ty)
288-
}
289-
290-
ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
291-
return Err(error(cx, LayoutError::Unknown(ty)));
292-
}
293-
})
294-
}
295-
29672
fn univariant_uninterned<'tcx>(
29773
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
29874
ty: Ty<'tcx>,
@@ -739,7 +515,7 @@ fn layout_of_uncached<'tcx>(
739515
})
740516
}
741517

742-
fn compute_array_count<'tcx>(
518+
pub(crate) fn compute_array_count<'tcx>(
743519
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
744520
mut count: ty::Const<'tcx>,
745521
) -> Option<u64> {
@@ -754,7 +530,7 @@ fn compute_array_count<'tcx>(
754530
count.try_eval_target_usize(tcx, param_env)
755531
}
756532

757-
fn ptr_metadata_scalar<'tcx>(
533+
pub(crate) fn ptr_metadata_scalar<'tcx>(
758534
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
759535
pointee: Ty<'tcx>,
760536
) -> Result<Option<Scalar>, &'tcx LayoutError<'tcx>> {

0 commit comments

Comments
 (0)