mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Auto merge of #13490 - HKalbasi:layout, r=jonas-schievink
Compute data layout of types cc #4091 Things that aren't working: * Closures * Generators (so no support for `Future` I think) * Opaque types * Type alias and associated types which may need normalization Things that show wrong result: * ~Enums with explicit discriminant~ * SIMD types * ~`NonZero*` and similar standard library items which control layout with special attributes~ At the user level, I didn't put much work, since I wasn't confident about what is the best way to present this information. Currently it shows size and align for ADTs, and size, align, offset for struct fields, in the hover, similar to clangd. I used it some days and I feel I liked it, but we may consider it too noisy and move it to an assist or command.
This commit is contained in:
commit
6e8a54d0f6
21 changed files with 1112 additions and 164 deletions
|
@ -39,12 +39,13 @@ use arrayvec::ArrayVec;
|
|||
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
adt::{ReprData, VariantData},
|
||||
adt::VariantData,
|
||||
body::{BodyDiagnostic, SyntheticSyntax},
|
||||
expr::{BindingAnnotation, LabelId, Pat, PatId},
|
||||
generics::{TypeOrConstParamData, TypeParamProvenance},
|
||||
item_tree::ItemTreeNode,
|
||||
lang_item::LangItemTarget,
|
||||
layout::{Layout, LayoutError, ReprOptions},
|
||||
nameres::{self, diagnostics::DefDiagnostic},
|
||||
per_ns::PerNs,
|
||||
resolver::{HasResolver, Resolver},
|
||||
|
@ -59,6 +60,7 @@ use hir_ty::{
|
|||
all_super_traits, autoderef,
|
||||
consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
|
||||
diagnostics::BodyValidationDiagnostic,
|
||||
layout::layout_of_ty,
|
||||
method_resolution::{self, TyFingerprint},
|
||||
primitive::UintTy,
|
||||
traits::FnTrait,
|
||||
|
@ -844,6 +846,10 @@ impl Field {
|
|||
self.parent.variant_data(db).fields()[self.id].name.clone()
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
u32::from(self.id.into_raw()) as usize
|
||||
}
|
||||
|
||||
/// Returns the type as in the signature of the struct (i.e., with
|
||||
/// placeholder types for type parameters). Only use this in the context of
|
||||
/// the field definition.
|
||||
|
@ -859,6 +865,10 @@ impl Field {
|
|||
Type::new(db, var_id, ty)
|
||||
}
|
||||
|
||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
layout_of_ty(db, &self.ty(db).ty)
|
||||
}
|
||||
|
||||
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
||||
self.parent
|
||||
}
|
||||
|
@ -900,7 +910,7 @@ impl Struct {
|
|||
Type::from_def(db, self.id)
|
||||
}
|
||||
|
||||
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> {
|
||||
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
||||
db.struct_data(self.id).repr.clone()
|
||||
}
|
||||
|
||||
|
@ -984,8 +994,30 @@ impl Enum {
|
|||
Type::new_for_crate(
|
||||
self.id.lookup(db.upcast()).container.krate(),
|
||||
TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
|
||||
Either::Left(builtin) => hir_def::builtin_type::BuiltinType::Int(builtin),
|
||||
Either::Right(builtin) => hir_def::builtin_type::BuiltinType::Uint(builtin),
|
||||
hir_def::layout::IntegerType::Pointer(sign) => match sign {
|
||||
true => hir_def::builtin_type::BuiltinType::Int(
|
||||
hir_def::builtin_type::BuiltinInt::Isize,
|
||||
),
|
||||
false => hir_def::builtin_type::BuiltinType::Uint(
|
||||
hir_def::builtin_type::BuiltinUint::Usize,
|
||||
),
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(i, sign) => match sign {
|
||||
true => hir_def::builtin_type::BuiltinType::Int(match i {
|
||||
hir_def::layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8,
|
||||
hir_def::layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16,
|
||||
hir_def::layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32,
|
||||
hir_def::layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64,
|
||||
hir_def::layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128,
|
||||
}),
|
||||
false => hir_def::builtin_type::BuiltinType::Uint(match i {
|
||||
hir_def::layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8,
|
||||
hir_def::layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16,
|
||||
hir_def::layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32,
|
||||
hir_def::layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64,
|
||||
hir_def::layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -1076,6 +1108,13 @@ impl Adt {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
if db.generic_params(self.into()).iter().count() != 0 {
|
||||
return Err(LayoutError::HasPlaceholder);
|
||||
}
|
||||
db.layout_of_adt(self.into(), Substitution::empty(Interner))
|
||||
}
|
||||
|
||||
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
||||
/// turned into unknown types, which is good for e.g. finding the most
|
||||
/// general set of completions, but will not look very nice when printed.
|
||||
|
@ -3033,7 +3072,7 @@ impl Type {
|
|||
|
||||
let adt = adt_id.into();
|
||||
match adt {
|
||||
Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })),
|
||||
Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue