about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-04-16 12:21:12 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-04-16 12:21:12 +0200
commit0bb9a173127b8ff270815e939cdc8dc0e9284dd8 (patch)
tree265aa90231838e93980dc3bb99efa7ba2934ff40
parentb218009f46dd012abcd2d9c2656c3dc498075368 (diff)
downloadrust-0bb9a173127b8ff270815e939cdc8dc0e9284dd8.tar.gz
rust-0bb9a173127b8ff270815e939cdc8dc0e9284dd8.zip
internal: Move layout logic from hir-def to hir-ty
-rw-r--r--crates/hir-def/src/data/adt.rs3
-rw-r--r--crates/hir-def/src/layout.rs98
-rw-r--r--crates/hir-def/src/lib.rs3
-rw-r--r--crates/hir-def/src/path.rs4
-rw-r--r--crates/hir-ty/src/db.rs9
-rw-r--r--crates/hir-ty/src/infer.rs2
-rw-r--r--crates/hir-ty/src/layout.rs57
-rw-r--r--crates/hir-ty/src/layout/adt.rs60
-rw-r--r--crates/hir-ty/src/layout/tests.rs10
-rw-r--r--crates/hir-ty/src/mir/eval.rs4
-rw-r--r--crates/hir-ty/src/mir/lower.rs3
-rw-r--r--crates/hir/src/lib.rs4
12 files changed, 120 insertions, 137 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 0b6a51fe764..0e4b033638a 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -13,7 +13,7 @@ use hir_expand::{
 };
 use intern::Interned;
 use la_arena::{Arena, ArenaMap};
-use rustc_abi::{Integer, IntegerType};
+use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
 use syntax::ast::{self, HasName, HasVisibility};
 
 use crate::{
@@ -22,7 +22,6 @@ use crate::{
     db::DefDatabase,
     item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
     lang_item::LangItem,
-    layout::{Align, ReprFlags, ReprOptions},
     nameres::diagnostics::DefDiagnostic,
     src::HasChildSource,
     src::HasSource,
diff --git a/crates/hir-def/src/layout.rs b/crates/hir-def/src/layout.rs
deleted file mode 100644
index 873936b5b76..00000000000
--- a/crates/hir-def/src/layout.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-//! Definitions needed for computing data layout of types.
-
-use std::cmp;
-
-use la_arena::{Idx, RawIdx};
-pub use rustc_abi::{
-    Abi, AbiAndPrefAlign, AddressSpace, Align, Endian, FieldsShape, Integer, IntegerType,
-    LayoutCalculator, Niche, Primitive, ReprFlags, ReprOptions, Scalar, Size, StructKind,
-    TargetDataLayout, TargetDataLayoutErrors, WrappingRange,
-};
-
-use crate::LocalEnumVariantId;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
-
-impl rustc_index::vec::Idx for RustcEnumVariantIdx {
-    fn new(idx: usize) -> Self {
-        RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
-    }
-
-    fn index(self) -> usize {
-        u32::from(self.0.into_raw()) as usize
-    }
-}
-
-pub type Layout = rustc_abi::LayoutS<RustcEnumVariantIdx>;
-pub type TagEncoding = rustc_abi::TagEncoding<RustcEnumVariantIdx>;
-pub type Variants = rustc_abi::Variants<RustcEnumVariantIdx>;
-
-pub trait IntegerExt {
-    fn repr_discr(
-        dl: &TargetDataLayout,
-        repr: &ReprOptions,
-        min: i128,
-        max: i128,
-    ) -> Result<(Integer, bool), LayoutError>;
-}
-
-impl IntegerExt for Integer {
-    /// Finds the appropriate Integer type and signedness for the given
-    /// signed discriminant range and `#[repr]` attribute.
-    /// N.B.: `u128` values above `i128::MAX` will be treated as signed, but
-    /// that shouldn't affect anything, other than maybe debuginfo.
-    fn repr_discr(
-        dl: &TargetDataLayout,
-        repr: &ReprOptions,
-        min: i128,
-        max: i128,
-    ) -> Result<(Integer, bool), LayoutError> {
-        // Theoretically, negative values could be larger in unsigned representation
-        // than the unsigned representation of the signed minimum. However, if there
-        // are any negative values, the only valid unsigned representation is u128
-        // which can fit all i128 values, so the result remains unaffected.
-        let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
-        let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
-
-        if let Some(ity) = repr.int {
-            let discr = Integer::from_attr(dl, ity);
-            let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
-            if discr < fit {
-                return Err(LayoutError::UserError(
-                    "Integer::repr_discr: `#[repr]` hint too small for \
-                      discriminant range of enum "
-                        .to_string(),
-                ));
-            }
-            return Ok((discr, ity.is_signed()));
-        }
-
-        let at_least = if repr.c() {
-            // This is usually I32, however it can be different on some platforms,
-            // notably hexagon and arm-none/thumb-none
-            dl.c_enum_min_size
-        } else {
-            // repr(Rust) enums try to be as small as possible
-            Integer::I8
-        };
-
-        // If there are no negative values, we can use the unsigned fit.
-        Ok(if min >= 0 {
-            (cmp::max(unsigned_fit, at_least), false)
-        } else {
-            (cmp::max(signed_fit, at_least), true)
-        })
-    }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub enum LayoutError {
-    UserError(String),
-    SizeOverflow,
-    TargetLayoutNotAvailable,
-    HasPlaceholder,
-    HasErrorType,
-    NotImplemented,
-    Unknown,
-}
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index ec9a8e80068..5a0c1b66b9c 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -29,7 +29,6 @@ pub mod item_tree;
 pub mod data;
 pub mod generics;
 pub mod lang_item;
-pub mod layout;
 
 pub mod hir;
 pub use self::hir::type_ref;
@@ -46,6 +45,8 @@ pub mod visibility;
 pub mod find_path;
 pub mod import_map;
 
+pub use rustc_abi as layout;
+
 #[cfg(test)]
 mod test_db;
 #[cfg(test)]
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index c67c29818f5..8cd287f7f30 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -9,14 +9,12 @@ use std::{
 use crate::{
     body::LowerCtx,
     lang_item::LangItemTarget,
-    type_ref::{ConstRefOrPath, LifetimeRef},
+    type_ref::{ConstRefOrPath, LifetimeRef, TypeBound, TypeRef},
 };
 use hir_expand::name::Name;
 use intern::Interned;
 use syntax::ast;
 
-use crate::type_ref::{TypeBound, TypeRef};
-
 pub use hir_expand::mod_path::{path, ModPath, PathKind};
 
 #[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index bd2dc0bc13d..c415689399f 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -5,11 +5,9 @@ use std::sync::Arc;
 
 use base_db::{impl_intern_key, salsa, CrateId, Upcast};
 use hir_def::{
-    db::DefDatabase,
-    hir::ExprId,
-    layout::{Layout, LayoutError, TargetDataLayout},
-    AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GenericDefId,
-    ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
+    db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, ConstId, ConstParamId,
+    DefWithBodyId, EnumVariantId, FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId,
+    TypeOrConstParamId, VariantId,
 };
 use la_arena::ArenaMap;
 use smallvec::SmallVec;
@@ -17,6 +15,7 @@ use smallvec::SmallVec;
 use crate::{
     chalk_db,
     consteval::ConstEvalError,
+    layout::{Layout, LayoutError},
     method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
     mir::{BorrowckResult, MirBody, MirLowerError},
     Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, InferenceResult,
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index d90ca77b55c..597bf4b9a88 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -18,11 +18,11 @@ use std::{convert::identity, ops::Index};
 
 use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
 use either::Either;
-use hir_def::hir::LabelId;
 use hir_def::{
     body::Body,
     builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
     data::{ConstData, StaticData},
+    hir::LabelId,
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, PatId},
     lang_item::{LangItem, LangItemTarget},
     layout::Integer,
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 23cad5e6fd3..512836afbf3 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -4,16 +4,19 @@ use base_db::CrateId;
 use chalk_ir::{AdtId, TyKind};
 use hir_def::{
     layout::{
-        Abi, FieldsShape, Integer, Layout, LayoutCalculator, LayoutError, Primitive, ReprOptions,
-        RustcEnumVariantIdx, Scalar, Size, StructKind, TargetDataLayout, Variants, WrappingRange,
+        Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
+        StructKind, TargetDataLayout, WrappingRange,
     },
-    LocalFieldId,
+    LocalEnumVariantId, LocalFieldId,
 };
+use la_arena::{Idx, RawIdx};
 use stdx::never;
 
-use crate::{consteval::try_const_usize, db::HirDatabase, Interner, Substitution, Ty};
+use crate::{
+    consteval::try_const_usize, db::HirDatabase, layout::adt::struct_variant_idx, Interner,
+    Substitution, Ty,
+};
 
-use self::adt::struct_variant_idx;
 pub use self::{
     adt::{layout_of_adt_query, layout_of_adt_recover},
     target::target_data_layout_query,
@@ -28,6 +31,34 @@ macro_rules! user_error {
 mod adt;
 mod target;
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
+
+impl rustc_index::vec::Idx for RustcEnumVariantIdx {
+    fn new(idx: usize) -> Self {
+        RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
+    }
+
+    fn index(self) -> usize {
+        u32::from(self.0.into_raw()) as usize
+    }
+}
+
+pub type Layout = LayoutS<RustcEnumVariantIdx>;
+pub type TagEncoding = hir_def::layout::TagEncoding<RustcEnumVariantIdx>;
+pub type Variants = hir_def::layout::Variants<RustcEnumVariantIdx>;
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum LayoutError {
+    UserError(String),
+    SizeOverflow,
+    TargetLayoutNotAvailable,
+    HasPlaceholder,
+    HasErrorType,
+    NotImplemented,
+    Unknown,
+}
+
 struct LayoutCx<'a> {
     krate: CrateId,
     target: &'a TargetDataLayout,
@@ -45,14 +76,6 @@ impl<'a> LayoutCalculator for LayoutCx<'a> {
     }
 }
 
-fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
-    Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
-}
-
-fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
-    Layout::scalar(dl, scalar_unit(dl, value))
-}
-
 pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Layout, LayoutError> {
     let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
     let cx = LayoutCx { krate, target: &target };
@@ -287,5 +310,13 @@ fn field_ty(
     db.field_types(def)[fd].clone().substitute(Interner, subst)
 }
 
+fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
+    Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
+}
+
+fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
+    Layout::scalar(dl, scalar_unit(dl, value))
+}
+
 #[cfg(test)]
 mod tests;
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index 3f3017deee9..9dbf9b2419c 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -1,16 +1,21 @@
 //! Compute the binary representation of structs, unions and enums
 
-use std::ops::Bound;
+use std::{cmp, ops::Bound};
 
 use hir_def::{
     data::adt::VariantData,
-    layout::{Integer, IntegerExt, Layout, LayoutCalculator, LayoutError, RustcEnumVariantIdx},
+    layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
     AdtId, EnumVariantId, HasModule, LocalEnumVariantId, VariantId,
 };
 use la_arena::RawIdx;
 use smallvec::SmallVec;
 
-use crate::{db::HirDatabase, lang_items::is_unsafe_cell, layout::field_ty, Substitution};
+use crate::{
+    db::HirDatabase,
+    lang_items::is_unsafe_cell,
+    layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
+    Substitution,
+};
 
 use super::{layout_of_ty, LayoutCx};
 
@@ -73,7 +78,7 @@ pub fn layout_of_adt_query(
             is_enum,
             is_unsafe_cell(db, def),
             layout_scalar_valid_range(db, def),
-            |min, max| Integer::repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
+            |min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
             variants.iter_enumerated().filter_map(|(id, _)| {
                 let AdtId::EnumId(e) = def else { return None };
                 let d =
@@ -125,3 +130,50 @@ pub fn layout_of_adt_recover(
 ) -> Result<Layout, LayoutError> {
     user_error!("infinite sized recursive type");
 }
+
+/// Finds the appropriate Integer type and signedness for the given
+/// signed discriminant range and `#[repr]` attribute.
+/// N.B.: `u128` values above `i128::MAX` will be treated as signed, but
+/// that shouldn't affect anything, other than maybe debuginfo.
+fn repr_discr(
+    dl: &TargetDataLayout,
+    repr: &ReprOptions,
+    min: i128,
+    max: i128,
+) -> Result<(Integer, bool), LayoutError> {
+    // Theoretically, negative values could be larger in unsigned representation
+    // than the unsigned representation of the signed minimum. However, if there
+    // are any negative values, the only valid unsigned representation is u128
+    // which can fit all i128 values, so the result remains unaffected.
+    let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
+    let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
+
+    if let Some(ity) = repr.int {
+        let discr = Integer::from_attr(dl, ity);
+        let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
+        if discr < fit {
+            return Err(LayoutError::UserError(
+                "Integer::repr_discr: `#[repr]` hint too small for \
+                      discriminant range of enum "
+                    .to_string(),
+            ));
+        }
+        return Ok((discr, ity.is_signed()));
+    }
+
+    let at_least = if repr.c() {
+        // This is usually I32, however it can be different on some platforms,
+        // notably hexagon and arm-none/thumb-none
+        dl.c_enum_min_size
+    } else {
+        // repr(Rust) enums try to be as small as possible
+        Integer::I8
+    };
+
+    // If there are no negative values, we can use the unsigned fit.
+    Ok(if min >= 0 {
+        (cmp::max(unsigned_fit, at_least), false)
+    } else {
+        (cmp::max(signed_fit, at_least), true)
+    })
+}
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index a0ffab55180..3cd0cd399c4 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -2,13 +2,15 @@ use std::collections::HashMap;
 
 use base_db::fixture::WithFixture;
 use chalk_ir::{AdtId, TyKind};
-use hir_def::{
-    db::DefDatabase,
+use hir_def::db::DefDatabase;
+
+use crate::{
+    db::HirDatabase,
     layout::{Layout, LayoutError},
+    test_db::TestDB,
+    Interner, Substitution,
 };
 
-use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution};
-
 use super::layout_of_ty;
 
 mod closure;
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 8c911b7f7b7..b39718fbdc4 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -10,7 +10,7 @@ use chalk_ir::{
 use hir_def::{
     builtin_type::BuiltinType,
     lang_item::{lang_attr, LangItem},
-    layout::{Layout, LayoutError, RustcEnumVariantIdx, TagEncoding, Variants},
+    layout::{TagEncoding, Variants},
     AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, VariantId,
 };
 use intern::Interned;
@@ -21,7 +21,7 @@ use crate::{
     db::HirDatabase,
     from_placeholder_idx,
     infer::{normalize, PointerCast},
-    layout::layout_of_ty,
+    layout::{layout_of_ty, Layout, LayoutError, RustcEnumVariantIdx},
     mapping::from_chalk,
     method_resolution::{is_dyn_method, lookup_impl_method},
     traits::FnTrait,
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 78a2d90f7fb..1f88cc57d06 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -11,7 +11,6 @@ use hir_def::{
         RecordFieldPat, RecordLitField,
     },
     lang_item::{LangItem, LangItemTarget},
-    layout::LayoutError,
     path::Path,
     resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
     AdtId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, LocalFieldId, TraitId,
@@ -26,7 +25,7 @@ use crate::{
     display::HirDisplay,
     infer::{CaptureKind, CapturedItem, TypeMismatch},
     inhabitedness::is_ty_uninhabited_from,
-    layout::layout_of_ty,
+    layout::{layout_of_ty, LayoutError},
     mapping::ToChalk,
     static_lifetime,
     utils::generics,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index e161c94a0ee..3e568a40215 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -45,7 +45,7 @@ use hir_def::{
     hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
     item_tree::ItemTreeNode,
     lang_item::{LangItem, LangItemTarget},
-    layout::{Layout, LayoutError, ReprOptions},
+    layout::ReprOptions,
     nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
@@ -61,7 +61,7 @@ use hir_ty::{
     consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
     diagnostics::BodyValidationDiagnostic,
     display::HexifiedConst,
-    layout::layout_of_ty,
+    layout::{layout_of_ty, Layout, LayoutError},
     method_resolution::{self, TyFingerprint},
     mir::{self, interpret_mir},
     primitive::UintTy,