Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c088958

Browse files
committed
Auto merge of rust-lang#14581 - Veykril:layout-ty, r=Veykril
internal: Move layout logic from hir-def to hir-ty
2 parents c28f538 + 0bb9a17 commit c088958

File tree

12 files changed

+120
-137
lines changed

12 files changed

+120
-137
lines changed

crates/hir-def/src/data/adt.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use hir_expand::{
1313
};
1414
use intern::Interned;
1515
use la_arena::{Arena, ArenaMap};
16-
use rustc_abi::{Integer, IntegerType};
16+
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
1717
use syntax::ast::{self, HasName, HasVisibility};
1818

1919
use crate::{
@@ -22,7 +22,6 @@ use crate::{
2222
db::DefDatabase,
2323
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
2424
lang_item::LangItem,
25-
layout::{Align, ReprFlags, ReprOptions},
2625
nameres::diagnostics::DefDiagnostic,
2726
src::HasChildSource,
2827
src::HasSource,

crates/hir-def/src/layout.rs

Lines changed: 0 additions & 98 deletions
This file was deleted.

crates/hir-def/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ pub mod item_tree;
2929
pub mod data;
3030
pub mod generics;
3131
pub mod lang_item;
32-
pub mod layout;
3332

3433
pub mod hir;
3534
pub use self::hir::type_ref;
@@ -46,6 +45,8 @@ pub mod visibility;
4645
pub mod find_path;
4746
pub mod import_map;
4847

48+
pub use rustc_abi as layout;
49+
4950
#[cfg(test)]
5051
mod test_db;
5152
#[cfg(test)]

crates/hir-def/src/path.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ use std::{
99
use crate::{
1010
body::LowerCtx,
1111
lang_item::LangItemTarget,
12-
type_ref::{ConstRefOrPath, LifetimeRef},
12+
type_ref::{ConstRefOrPath, LifetimeRef, TypeBound, TypeRef},
1313
};
1414
use hir_expand::name::Name;
1515
use intern::Interned;
1616
use syntax::ast;
1717

18-
use crate::type_ref::{TypeBound, TypeRef};
19-
2018
pub use hir_expand::mod_path::{path, ModPath, PathKind};
2119

2220
#[derive(Debug, Clone, PartialEq, Eq)]

crates/hir-ty/src/db.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@ use std::sync::Arc;
55

66
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
77
use hir_def::{
8-
db::DefDatabase,
9-
hir::ExprId,
10-
layout::{Layout, LayoutError, TargetDataLayout},
11-
AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GenericDefId,
12-
ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
8+
db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, ConstId, ConstParamId,
9+
DefWithBodyId, EnumVariantId, FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId,
10+
TypeOrConstParamId, VariantId,
1311
};
1412
use la_arena::ArenaMap;
1513
use smallvec::SmallVec;
1614

1715
use crate::{
1816
chalk_db,
1917
consteval::ConstEvalError,
18+
layout::{Layout, LayoutError},
2019
method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
2120
mir::{BorrowckResult, MirBody, MirLowerError},
2221
Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, InferenceResult,

crates/hir-ty/src/infer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use std::{convert::identity, ops::Index};
1818

1919
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
2020
use either::Either;
21-
use hir_def::hir::LabelId;
2221
use hir_def::{
2322
body::Body,
2423
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
2524
data::{ConstData, StaticData},
25+
hir::LabelId,
2626
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, PatId},
2727
lang_item::{LangItem, LangItemTarget},
2828
layout::Integer,

crates/hir-ty/src/layout.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@ use base_db::CrateId;
44
use chalk_ir::{AdtId, TyKind};
55
use hir_def::{
66
layout::{
7-
Abi, FieldsShape, Integer, Layout, LayoutCalculator, LayoutError, Primitive, ReprOptions,
8-
RustcEnumVariantIdx, Scalar, Size, StructKind, TargetDataLayout, Variants, WrappingRange,
7+
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
8+
StructKind, TargetDataLayout, WrappingRange,
99
},
10-
LocalFieldId,
10+
LocalEnumVariantId, LocalFieldId,
1111
};
12+
use la_arena::{Idx, RawIdx};
1213
use stdx::never;
1314

14-
use crate::{consteval::try_const_usize, db::HirDatabase, Interner, Substitution, Ty};
15+
use crate::{
16+
consteval::try_const_usize, db::HirDatabase, layout::adt::struct_variant_idx, Interner,
17+
Substitution, Ty,
18+
};
1519

16-
use self::adt::struct_variant_idx;
1720
pub use self::{
1821
adt::{layout_of_adt_query, layout_of_adt_recover},
1922
target::target_data_layout_query,
@@ -28,6 +31,34 @@ macro_rules! user_error {
2831
mod adt;
2932
mod target;
3033

34+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35+
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
36+
37+
impl rustc_index::vec::Idx for RustcEnumVariantIdx {
38+
fn new(idx: usize) -> Self {
39+
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
40+
}
41+
42+
fn index(self) -> usize {
43+
u32::from(self.0.into_raw()) as usize
44+
}
45+
}
46+
47+
pub type Layout = LayoutS<RustcEnumVariantIdx>;
48+
pub type TagEncoding = hir_def::layout::TagEncoding<RustcEnumVariantIdx>;
49+
pub type Variants = hir_def::layout::Variants<RustcEnumVariantIdx>;
50+
51+
#[derive(Debug, PartialEq, Eq, Clone)]
52+
pub enum LayoutError {
53+
UserError(String),
54+
SizeOverflow,
55+
TargetLayoutNotAvailable,
56+
HasPlaceholder,
57+
HasErrorType,
58+
NotImplemented,
59+
Unknown,
60+
}
61+
3162
struct LayoutCx<'a> {
3263
krate: CrateId,
3364
target: &'a TargetDataLayout,
@@ -45,14 +76,6 @@ impl<'a> LayoutCalculator for LayoutCx<'a> {
4576
}
4677
}
4778

48-
fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
49-
Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
50-
}
51-
52-
fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
53-
Layout::scalar(dl, scalar_unit(dl, value))
54-
}
55-
5679
pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Layout, LayoutError> {
5780
let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
5881
let cx = LayoutCx { krate, target: &target };
@@ -287,5 +310,13 @@ fn field_ty(
287310
db.field_types(def)[fd].clone().substitute(Interner, subst)
288311
}
289312

313+
fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
314+
Scalar::Initialized { value, valid_range: WrappingRange::full(value.size(dl)) }
315+
}
316+
317+
fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
318+
Layout::scalar(dl, scalar_unit(dl, value))
319+
}
320+
290321
#[cfg(test)]
291322
mod tests;

crates/hir-ty/src/layout/adt.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
//! Compute the binary representation of structs, unions and enums
22
3-
use std::ops::Bound;
3+
use std::{cmp, ops::Bound};
44

55
use hir_def::{
66
data::adt::VariantData,
7-
layout::{Integer, IntegerExt, Layout, LayoutCalculator, LayoutError, RustcEnumVariantIdx},
7+
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
88
AdtId, EnumVariantId, HasModule, LocalEnumVariantId, VariantId,
99
};
1010
use la_arena::RawIdx;
1111
use smallvec::SmallVec;
1212

13-
use crate::{db::HirDatabase, lang_items::is_unsafe_cell, layout::field_ty, Substitution};
13+
use crate::{
14+
db::HirDatabase,
15+
lang_items::is_unsafe_cell,
16+
layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
17+
Substitution,
18+
};
1419

1520
use super::{layout_of_ty, LayoutCx};
1621

@@ -73,7 +78,7 @@ pub fn layout_of_adt_query(
7378
is_enum,
7479
is_unsafe_cell(db, def),
7580
layout_scalar_valid_range(db, def),
76-
|min, max| Integer::repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
81+
|min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
7782
variants.iter_enumerated().filter_map(|(id, _)| {
7883
let AdtId::EnumId(e) = def else { return None };
7984
let d =
@@ -125,3 +130,50 @@ pub fn layout_of_adt_recover(
125130
) -> Result<Layout, LayoutError> {
126131
user_error!("infinite sized recursive type");
127132
}
133+
134+
/// Finds the appropriate Integer type and signedness for the given
135+
/// signed discriminant range and `#[repr]` attribute.
136+
/// N.B.: `u128` values above `i128::MAX` will be treated as signed, but
137+
/// that shouldn't affect anything, other than maybe debuginfo.
138+
fn repr_discr(
139+
dl: &TargetDataLayout,
140+
repr: &ReprOptions,
141+
min: i128,
142+
max: i128,
143+
) -> Result<(Integer, bool), LayoutError> {
144+
// Theoretically, negative values could be larger in unsigned representation
145+
// than the unsigned representation of the signed minimum. However, if there
146+
// are any negative values, the only valid unsigned representation is u128
147+
// which can fit all i128 values, so the result remains unaffected.
148+
let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
149+
let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
150+
151+
if let Some(ity) = repr.int {
152+
let discr = Integer::from_attr(dl, ity);
153+
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
154+
if discr < fit {
155+
return Err(LayoutError::UserError(
156+
"Integer::repr_discr: `#[repr]` hint too small for \
157+
discriminant range of enum "
158+
.to_string(),
159+
));
160+
}
161+
return Ok((discr, ity.is_signed()));
162+
}
163+
164+
let at_least = if repr.c() {
165+
// This is usually I32, however it can be different on some platforms,
166+
// notably hexagon and arm-none/thumb-none
167+
dl.c_enum_min_size
168+
} else {
169+
// repr(Rust) enums try to be as small as possible
170+
Integer::I8
171+
};
172+
173+
// If there are no negative values, we can use the unsigned fit.
174+
Ok(if min >= 0 {
175+
(cmp::max(unsigned_fit, at_least), false)
176+
} else {
177+
(cmp::max(signed_fit, at_least), true)
178+
})
179+
}

crates/hir-ty/src/layout/tests.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use std::collections::HashMap;
22

33
use base_db::fixture::WithFixture;
44
use chalk_ir::{AdtId, TyKind};
5-
use hir_def::{
6-
db::DefDatabase,
5+
use hir_def::db::DefDatabase;
6+
7+
use crate::{
8+
db::HirDatabase,
79
layout::{Layout, LayoutError},
10+
test_db::TestDB,
11+
Interner, Substitution,
812
};
913

10-
use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution};
11-
1214
use super::layout_of_ty;
1315

1416
mod closure;

crates/hir-ty/src/mir/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use chalk_ir::{
1010
use hir_def::{
1111
builtin_type::BuiltinType,
1212
lang_item::{lang_attr, LangItem},
13-
layout::{Layout, LayoutError, RustcEnumVariantIdx, TagEncoding, Variants},
13+
layout::{TagEncoding, Variants},
1414
AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, VariantId,
1515
};
1616
use intern::Interned;
@@ -21,7 +21,7 @@ use crate::{
2121
db::HirDatabase,
2222
from_placeholder_idx,
2323
infer::{normalize, PointerCast},
24-
layout::layout_of_ty,
24+
layout::{layout_of_ty, Layout, LayoutError, RustcEnumVariantIdx},
2525
mapping::from_chalk,
2626
method_resolution::{is_dyn_method, lookup_impl_method},
2727
traits::FnTrait,

0 commit comments

Comments
 (0)