Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/layout.rs')
| -rw-r--r-- | crates/hir-ty/src/layout.rs | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index ca39fde118..3c6489fa97 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -1,12 +1,15 @@ //! Compute the binary representation of a type +use std::sync::Arc; + use chalk_ir::{AdtId, TyKind}; pub(self) use hir_def::layout::*; use hir_def::LocalFieldId; +use stdx::never; use crate::{db::HirDatabase, Interner, Substitution, Ty}; -use self::adt::univariant; +use self::adt::struct_variant_idx; pub use self::{ adt::{layout_of_adt_query, layout_of_adt_recover}, target::current_target_data_layout_query, @@ -21,6 +24,22 @@ macro_rules! user_error { mod adt; mod target; +struct LayoutCx<'a> { + db: &'a dyn HirDatabase, +} + +impl LayoutCalculator for LayoutCx<'_> { + type TargetDataLayoutRef = Arc<TargetDataLayout>; + + fn delay_bug(&self, txt: &str) { + never!("{}", txt); + } + + fn current_data_layout(&self) -> Arc<TargetDataLayout> { + self.db.current_target_data_layout() + } +} + fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar { Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) } } @@ -29,34 +48,9 @@ fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout { Layout::scalar(dl, scalar_unit(dl, value)) } -fn scalar_pair(dl: &TargetDataLayout, a: Scalar, b: Scalar) -> Layout { - let b_align = b.align(dl); - let align = a.align(dl).max(b_align).max(dl.aggregate_align); - let b_offset = a.size(dl).align_to(b_align.abi); - let size = b_offset.checked_add(b.size(dl), dl).unwrap().align_to(align.abi); - - // HACK(nox): We iter on `b` and then `a` because `max_by_key` - // returns the last maximum. - let largest_niche = Niche::from_scalar(dl, b_offset, b) - .into_iter() - .chain(Niche::from_scalar(dl, Size::ZERO, a)) - .max_by_key(|niche| niche.available(dl)); - - Layout { - variants: Variants::Single, - fields: FieldsShape::Arbitrary { - offsets: vec![Size::ZERO, b_offset], - memory_index: vec![0, 1], - }, - abi: Abi::ScalarPair(a, b), - largest_niche, - align, - size, - } -} - pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError> { let dl = &*db.current_target_data_layout(); + let cx = LayoutCx { db }; Ok(match ty.kind(Interner) { TyKind::Adt(AdtId(def), subst) => db.layout_of_adt(*def, subst.clone())?, TyKind::Scalar(s) => match s { @@ -113,14 +107,13 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError TyKind::Tuple(len, tys) => { let kind = if *len == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; - univariant( - dl, - &tys.iter(Interner) - .map(|k| layout_of_ty(db, k.assert_ty_ref(Interner))) - .collect::<Result<Vec<_>, _>>()?, - &ReprOptions::default(), - kind, - )? + let fields = tys + .iter(Interner) + .map(|k| layout_of_ty(db, k.assert_ty_ref(Interner))) + .collect::<Result<Vec<_>, _>>()?; + let fields = fields.iter().collect::<Vec<_>>(); + let fields = fields.iter().collect::<Vec<_>>(); + cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? } TyKind::Array(element, count) => { let count = match count.data(Interner).value { @@ -146,7 +139,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError let largest_niche = if count != 0 { element.largest_niche } else { None }; Layout { - variants: Variants::Single, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count }, abi, largest_niche, @@ -157,7 +150,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError TyKind::Slice(element) => { let element = layout_of_ty(db, element)?; Layout { - variants: Variants::Single, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count: 0 }, abi: Abi::Aggregate { sized: false }, largest_niche: None, @@ -194,13 +187,11 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError }; // Effectively a (ptr, meta) tuple. - scalar_pair(dl, data_ptr, metadata) - } - TyKind::FnDef(_, _) => { - univariant(dl, &[], &ReprOptions::default(), StructKind::AlwaysSized)? + cx.scalar_pair(data_ptr, metadata) } + TyKind::FnDef(_, _) => layout_of_unit(&cx, dl)?, TyKind::Str => Layout { - variants: Variants::Single, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, abi: Abi::Aggregate { sized: false }, largest_niche: None, @@ -208,7 +199,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError size: Size::ZERO, }, TyKind::Never => Layout { - variants: Variants::Single, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Primitive, abi: Abi::Uninhabited, largest_niche: None, @@ -216,7 +207,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError size: Size::ZERO, }, TyKind::Dyn(_) | TyKind::Foreign(_) => { - let mut unit = univariant(dl, &[], &ReprOptions::default(), StructKind::AlwaysSized)?; + let mut unit = layout_of_unit(&cx, dl)?; match unit.abi { Abi::Aggregate { ref mut sized } => *sized = false, _ => user_error!("bug"), @@ -241,6 +232,16 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty) -> Result<Layout, LayoutError }) } +fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> { + cx.univariant::<RustcEnumVariantIdx, &&Layout>( + &dl, + &[], + &ReprOptions::default(), + StructKind::AlwaysSized, + ) + .ok_or(LayoutError::Unknown) +} + fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { match pointee.kind(Interner) { TyKind::Adt(AdtId(adt), subst) => match adt { |