about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src/layout_naive.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src/layout_naive.rs')
-rw-r--r--compiler/rustc_ty_utils/src/layout_naive.rs322
1 files changed, 0 insertions, 322 deletions
diff --git a/compiler/rustc_ty_utils/src/layout_naive.rs b/compiler/rustc_ty_utils/src/layout_naive.rs
deleted file mode 100644
index 3070ab59d53..00000000000
--- a/compiler/rustc_ty_utils/src/layout_naive.rs
+++ /dev/null
@@ -1,322 +0,0 @@
-use rustc_middle::query::Providers;
-use rustc_middle::ty::layout::{
-    IntegerExt, LayoutCx, LayoutError, LayoutOf, NaiveAbi, NaiveLayout, NaiveNiches,
-    TyAndNaiveLayout,
-};
-use rustc_middle::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::DUMMY_SP;
-use rustc_target::abi::*;
-
-use std::ops::Bound;
-
-use crate::layout::{compute_array_count, ptr_metadata_scalar};
-
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers { naive_layout_of, ..*providers };
-}
-
-#[instrument(skip(tcx, query), level = "debug")]
-fn naive_layout_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<TyAndNaiveLayout<'tcx>, &'tcx LayoutError<'tcx>> {
-    let (param_env, ty) = query.into_parts();
-    debug!(?ty);
-
-    let param_env = param_env.with_reveal_all_normalized(tcx);
-    let unnormalized_ty = ty;
-
-    // FIXME: We might want to have two different versions of `layout_of`:
-    // One that can be called after typecheck has completed and can use
-    // `normalize_erasing_regions` here and another one that can be called
-    // before typecheck has completed and uses `try_normalize_erasing_regions`.
-    let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
-        Ok(t) => t,
-        Err(normalization_error) => {
-            return Err(tcx
-                .arena
-                .alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
-        }
-    };
-
-    if ty != unnormalized_ty {
-        // Ensure this layout is also cached for the normalized type.
-        return tcx.naive_layout_of(param_env.and(ty));
-    }
-
-    let cx = LayoutCx { tcx, param_env };
-    let layout = naive_layout_of_uncached(&cx, ty)?;
-    Ok(TyAndNaiveLayout { ty, layout })
-}
-
-fn error<'tcx>(
-    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
-    err: LayoutError<'tcx>,
-) -> &'tcx LayoutError<'tcx> {
-    cx.tcx.arena.alloc(err)
-}
-
-fn naive_layout_of_uncached<'tcx>(
-    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
-    ty: Ty<'tcx>,
-) -> Result<NaiveLayout, &'tcx LayoutError<'tcx>> {
-    let tcx = cx.tcx;
-    let dl = cx.data_layout();
-
-    let scalar = |niched: bool, value: Primitive| NaiveLayout {
-        abi: NaiveAbi::Scalar(value),
-        niches: if niched { NaiveNiches::Some } else { NaiveNiches::None },
-        size: value.size(dl),
-        align: value.align(dl).abi,
-        exact: true,
-    };
-
-    let univariant = |fields: &mut dyn Iterator<Item = Ty<'tcx>>,
-                      repr: &ReprOptions|
-     -> Result<NaiveLayout, &'tcx LayoutError<'tcx>> {
-        if repr.pack.is_some() && repr.align.is_some() {
-            cx.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
-            return Err(error(cx, LayoutError::Unknown(ty)));
-        }
-
-        let linear = repr.inhibit_struct_field_reordering_opt();
-        let pack = repr.pack.unwrap_or(Align::MAX);
-        let mut layout = NaiveLayout::EMPTY;
-
-        for field in fields {
-            let field = cx.naive_layout_of(field)?.packed(pack);
-            if linear {
-                layout = layout.pad_to_align(field.align);
-            }
-            layout = layout
-                .concat(&field, dl)
-                .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
-        }
-
-        if let Some(align) = repr.align {
-            layout = layout.align_to(align);
-        }
-
-        if linear {
-            layout.abi = layout.abi.as_aggregate();
-        }
-
-        Ok(layout.pad_to_align(layout.align))
-    };
-
-    debug_assert!(!ty.has_non_region_infer());
-
-    Ok(match *ty.kind() {
-        // Basic scalars
-        ty::Bool => scalar(true, Int(I8, false)),
-        ty::Char => scalar(true, Int(I32, false)),
-        ty::Int(ity) => scalar(false, Int(Integer::from_int_ty(dl, ity), true)),
-        ty::Uint(ity) => scalar(false, Int(Integer::from_uint_ty(dl, ity), false)),
-        ty::Float(fty) => scalar(
-            false,
-            match fty {
-                ty::FloatTy::F32 => F32,
-                ty::FloatTy::F64 => F64,
-            },
-        ),
-        ty::FnPtr(_) => scalar(true, Pointer(dl.instruction_address_space)),
-
-        // The never type.
-        ty::Never => NaiveLayout { abi: NaiveAbi::Uninhabited, ..NaiveLayout::EMPTY },
-
-        // Potentially-wide pointers.
-        ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
-            let data_ptr = scalar(!ty.is_unsafe_ptr(), Pointer(AddressSpace::DATA));
-            if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
-                // Effectively a (ptr, meta) tuple.
-                let meta = scalar(!metadata.is_always_valid(dl), metadata.primitive());
-                let l = data_ptr
-                    .concat(&meta, dl)
-                    .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
-                l.pad_to_align(l.align)
-            } else {
-                // No metadata, this is a thin pointer.
-                data_ptr
-            }
-        }
-
-        ty::Dynamic(_, _, ty::DynStar) => {
-            let ptr = scalar(false, Pointer(AddressSpace::DATA));
-            let vtable = scalar(true, Pointer(AddressSpace::DATA));
-            ptr.concat(&vtable, dl).ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?
-        }
-
-        // Arrays and slices.
-        ty::Array(element, count) => {
-            let count = compute_array_count(cx, count)
-                .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
-            let element = cx.naive_layout_of(element)?;
-            NaiveLayout {
-                abi: element.abi.as_aggregate(),
-                size: element
-                    .size
-                    .checked_mul(count, cx)
-                    .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?,
-                niches: if count == 0 { NaiveNiches::None } else { element.niches },
-                ..*element
-            }
-        }
-        ty::Slice(element) => NaiveLayout {
-            abi: NaiveAbi::Unsized,
-            size: Size::ZERO,
-            niches: NaiveNiches::None,
-            ..*cx.naive_layout_of(element)?
-        },
-
-        ty::FnDef(..) => NaiveLayout::EMPTY,
-
-        // Unsized types.
-        ty::Str | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
-            NaiveLayout { abi: NaiveAbi::Unsized, ..NaiveLayout::EMPTY }
-        }
-
-        // FIXME(reference_niches): try to actually compute a reasonable layout estimate,
-        // without duplicating too much code from `generator_layout`.
-        ty::Generator(..) => {
-            NaiveLayout { exact: false, niches: NaiveNiches::Maybe, ..NaiveLayout::EMPTY }
-        }
-
-        ty::Closure(_, ref substs) => {
-            univariant(&mut substs.as_closure().upvar_tys(), &ReprOptions::default())?
-        }
-
-        ty::Tuple(tys) => univariant(&mut tys.iter(), &ReprOptions::default())?,
-
-        ty::Adt(def, substs) if def.is_union() => {
-            assert_eq!(def.variants().len(), 1, "union should have a single variant");
-            let repr = def.repr();
-            let pack = repr.pack.unwrap_or(Align::MAX);
-            if repr.pack.is_some() && repr.align.is_some() {
-                cx.tcx.sess.delay_span_bug(DUMMY_SP, "union cannot be packed and aligned");
-                return Err(error(cx, LayoutError::Unknown(ty)));
-            }
-
-            let mut layout = NaiveLayout {
-                // Unions never have niches.
-                niches: NaiveNiches::None,
-                ..NaiveLayout::EMPTY
-            };
-
-            for f in &def.variants()[FIRST_VARIANT].fields {
-                let field = cx.naive_layout_of(f.ty(tcx, substs))?;
-                layout = layout.union(&field.packed(pack));
-            }
-
-            // Unions are always inhabited, and never scalar if `repr(C)`.
-            if !matches!(layout.abi, NaiveAbi::Scalar(_)) || repr.inhibit_enum_layout_opt() {
-                layout.abi = NaiveAbi::Sized;
-            }
-
-            if let Some(align) = repr.align {
-                layout = layout.align_to(align);
-            }
-            layout.pad_to_align(layout.align)
-        }
-
-        ty::Adt(def, substs) => {
-            let repr = def.repr();
-            let mut layout = NaiveLayout {
-                // An ADT with no inhabited variants should have an uninhabited ABI.
-                abi: NaiveAbi::Uninhabited,
-                ..NaiveLayout::EMPTY
-            };
-
-            let mut empty_variants = 0;
-            for v in def.variants() {
-                let mut fields = v.fields.iter().map(|f| f.ty(tcx, substs));
-                let vlayout = univariant(&mut fields, &repr)?;
-
-                if vlayout.size == Size::ZERO && vlayout.exact {
-                    empty_variants += 1;
-                } else {
-                    // Remember the niches of the last seen variant.
-                    layout.niches = vlayout.niches;
-                }
-
-                layout = layout.union(&vlayout);
-            }
-
-            if def.is_enum() {
-                let may_need_discr = match def.variants().len() {
-                    0 | 1 => false,
-                    // Simple Option-like niche optimization.
-                    // Handling this special case allows enums like `Option<&T>`
-                    // to be recognized as `PointerLike` and to be transmutable
-                    // in generic contexts.
-                    2 if empty_variants == 1 && layout.niches == NaiveNiches::Some => {
-                        layout.niches = NaiveNiches::Maybe; // fill up the niche.
-                        false
-                    }
-                    _ => true,
-                };
-
-                if may_need_discr || repr.inhibit_enum_layout_opt() {
-                    // For simplicity, assume that the discriminant always get niched.
-                    // This will be wrong in many cases, which will cause the size (and
-                    // sometimes the alignment) to be underestimated.
-                    // FIXME(reference_niches): Be smarter here.
-                    layout.niches = NaiveNiches::Maybe;
-                    layout = layout.inexact();
-                }
-            } else {
-                assert_eq!(def.variants().len(), 1, "struct should have a single variant");
-
-                // We don't compute exact alignment for SIMD structs.
-                if repr.simd() {
-                    layout = layout.inexact();
-                }
-
-                // `UnsafeCell` hides all niches.
-                if def.is_unsafe_cell() {
-                    layout.niches = NaiveNiches::None;
-                }
-            }
-
-            let valid_range = tcx.layout_scalar_valid_range(def.did());
-            if valid_range != (Bound::Unbounded, Bound::Unbounded) {
-                let get = |bound, default| match bound {
-                    Bound::Unbounded => default,
-                    Bound::Included(v) => v,
-                    Bound::Excluded(_) => bug!("exclusive `layout_scalar_valid_range` bound"),
-                };
-
-                let valid_range = WrappingRange {
-                    start: get(valid_range.0, 0),
-                    // FIXME: this is wrong for scalar-pair ABIs. Fortunately, the
-                    // only type this could currently affect is`NonNull<T: !Sized>`,
-                    // and the `NaiveNiches` result still ends up correct.
-                    end: get(valid_range.1, layout.size.unsigned_int_max()),
-                };
-                assert!(
-                    valid_range.is_in_range_for(layout.size),
-                    "`layout_scalar_valid_range` values are out of bounds",
-                );
-                if !valid_range.is_full_for(layout.size) {
-                    layout.niches = NaiveNiches::Some;
-                }
-            }
-
-            layout.pad_to_align(layout.align)
-        }
-
-        // Types with no meaningful known layout.
-        ty::Alias(..) => {
-            // NOTE(eddyb) `layout_of` query should've normalized these away,
-            // if that was possible, so there's no reason to try again here.
-            return Err(error(cx, LayoutError::Unknown(ty)));
-        }
-
-        ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
-            bug!("Layout::compute: unexpected type `{}`", ty)
-        }
-
-        ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
-            return Err(error(cx, LayoutError::Unknown(ty)));
-        }
-    })
-}