Skip to content

Commit 4e6cce6

Browse files
committed
Add render configs for memory layout hovers
1 parent 76d8650 commit 4e6cce6

File tree

12 files changed

+420
-182
lines changed

12 files changed

+420
-182
lines changed

crates/hir/src/lib.rs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use hir_def::{
4545
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
4646
item_tree::ItemTreeNode,
4747
lang_item::LangItemTarget,
48-
layout::{self, ReprOptions},
48+
layout::{self, ReprOptions, TargetDataLayout},
4949
macro_id_to_def_id,
5050
nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
5151
per_ns::PerNs,
@@ -62,7 +62,7 @@ use hir_ty::{
6262
consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
6363
diagnostics::BodyValidationDiagnostic,
6464
display::HexifiedConst,
65-
layout::{Layout as TyLayout, LayoutError, RustcEnumVariantIdx, TagEncoding},
65+
layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding},
6666
method_resolution::{self, TyFingerprint},
6767
mir::{self, interpret_mir},
6868
primitive::UintTy,
@@ -133,6 +133,7 @@ pub use {
133133
},
134134
hir_ty::{
135135
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
136+
layout::LayoutError,
136137
mir::MirEvalError,
137138
PointerCast, Safety,
138139
},
@@ -962,7 +963,8 @@ impl Field {
962963
}
963964

964965
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
965-
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into()).map(Layout)
966+
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
967+
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
966968
}
967969

968970
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
@@ -1135,23 +1137,8 @@ impl Enum {
11351137
self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
11361138
}
11371139

1138-
pub fn layout(self, db: &dyn HirDatabase) -> Result<(Layout, usize), LayoutError> {
1139-
let layout = Adt::from(self).layout(db)?;
1140-
let tag_size =
1141-
if let layout::Variants::Multiple { tag, tag_encoding, .. } = &layout.0.variants {
1142-
match tag_encoding {
1143-
TagEncoding::Direct => {
1144-
let target_data_layout = db
1145-
.target_data_layout(self.module(db).krate().id)
1146-
.ok_or(LayoutError::TargetLayoutNotAvailable)?;
1147-
tag.size(&*target_data_layout).bytes_usize()
1148-
}
1149-
TagEncoding::Niche { .. } => 0,
1150-
}
1151-
} else {
1152-
0
1153-
};
1154-
Ok((layout, tag_size))
1140+
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1141+
Adt::from(self).layout(db)
11551142
}
11561143
}
11571144

@@ -1214,19 +1201,16 @@ impl Variant {
12141201
db.const_eval_discriminant(self.into())
12151202
}
12161203

1217-
/// Return layout of the variant and tag size of the parent enum.
1218-
pub fn layout(&self, db: &dyn HirDatabase) -> Result<(Layout, usize), LayoutError> {
1204+
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
12191205
let parent_enum = self.parent_enum(db);
1220-
let (parent_layout, tag_size) = parent_enum.layout(db)?;
1221-
Ok((
1222-
match &parent_layout.0.variants {
1223-
layout::Variants::Multiple { variants, .. } => {
1224-
Layout(Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()))
1225-
}
1226-
_ => parent_layout,
1227-
},
1228-
tag_size,
1229-
))
1206+
let parent_layout = parent_enum.layout(db)?;
1207+
Ok(match &parent_layout.0.variants {
1208+
layout::Variants::Multiple { variants, .. } => Layout(
1209+
Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()),
1210+
db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
1211+
),
1212+
_ => parent_layout,
1213+
})
12301214
}
12311215
}
12321216

@@ -1259,7 +1243,9 @@ impl Adt {
12591243
if db.generic_params(self.into()).iter().count() != 0 {
12601244
return Err(LayoutError::HasPlaceholder);
12611245
}
1262-
db.layout_of_adt(self.into(), Substitution::empty(Interner), self.krate(db).id).map(Layout)
1246+
let krate = self.krate(db).id;
1247+
db.layout_of_adt(self.into(), Substitution::empty(Interner), krate)
1248+
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
12631249
}
12641250

12651251
/// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -4244,7 +4230,8 @@ impl Type {
42444230
}
42454231

42464232
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
4247-
db.layout_of_ty(self.ty.clone(), self.env.krate).map(Layout)
4233+
db.layout_of_ty(self.ty.clone(), self.env.krate)
4234+
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
42484235
}
42494236
}
42504237

@@ -4356,7 +4343,7 @@ fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::Closu
43564343
}
43574344

43584345
#[derive(Clone, Debug, Eq, PartialEq)]
4359-
pub struct Layout(Arc<TyLayout>);
4346+
pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);
43604347

43614348
impl Layout {
43624349
pub fn size(&self) -> u64 {
@@ -4367,8 +4354,8 @@ impl Layout {
43674354
self.0.align.abi.bytes()
43684355
}
43694356

4370-
pub fn niches(&self, db: &dyn HirDatabase, krate: Crate) -> Option<u128> {
4371-
Some(self.0.largest_niche?.available(&*db.target_data_layout(krate.id)?))
4357+
pub fn niches(&self) -> Option<u128> {
4358+
Some(self.0.largest_niche?.available(&*self.1))
43724359
}
43734360

43744361
pub fn field_offset(&self, idx: usize) -> Option<u64> {
@@ -4382,6 +4369,19 @@ impl Layout {
43824369
layout::FieldsShape::Arbitrary { ref offsets, .. } => Some(offsets.get(idx)?.bytes()),
43834370
}
43844371
}
4372+
4373+
pub fn enum_tag_size(&self) -> Option<usize> {
4374+
let tag_size =
4375+
if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
4376+
match tag_encoding {
4377+
TagEncoding::Direct => tag.size(&*self.1).bytes_usize(),
4378+
TagEncoding::Niche { .. } => 0,
4379+
}
4380+
} else {
4381+
return None;
4382+
};
4383+
Some(tag_size)
4384+
}
43854385
}
43864386

43874387
#[derive(Copy, Clone, Debug, Eq, PartialEq)]

crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ pub(crate) fn convert_named_struct_to_tuple_struct(
5555
// XXX: We don't currently provide this assist for struct definitions inside macros, but if we
5656
// are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
5757
// too.
58-
let strukt = ctx.find_node_at_offset::<Either<ast::Struct, ast::Variant>>()?;
58+
let name = ctx.find_node_at_offset::<ast::Name>()?;
59+
let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?;
5960
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
6061
let record_fields = match field_list {
6162
ast::FieldList::RecordFieldList(it) => it,

crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
5050
acc: &mut Assists,
5151
ctx: &AssistContext<'_>,
5252
) -> Option<()> {
53-
let strukt = ctx.find_node_at_offset::<Either<ast::Struct, ast::Variant>>()?;
53+
let name = ctx.find_node_at_offset::<ast::Name>()?;
54+
let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?;
5455
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
5556
let tuple_fields = match field_list {
5657
ast::FieldList::TupleFieldList(it) => it,

crates/ide-assists/src/tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,9 @@ fn assist_order_field_struct() {
273273
assert_eq!(assists.next().expect("expected assist").label, "Generate a getter method");
274274
assert_eq!(assists.next().expect("expected assist").label, "Generate a mut getter method");
275275
assert_eq!(assists.next().expect("expected assist").label, "Generate a setter method");
276-
assert_eq!(assists.next().expect("expected assist").label, "Convert to tuple struct");
277276
assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
277+
assert_eq!(assists.next().expect("expected assist").label, "Generate `new`");
278+
assert_eq!(assists.next().map(|it| it.label.to_string()), None);
278279
}
279280

280281
#[test]

crates/ide/src/hover.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,27 @@ use crate::{
2727
#[derive(Clone, Debug, PartialEq, Eq)]
2828
pub struct HoverConfig {
2929
pub links_in_hover: bool,
30-
pub memory_layout: bool,
30+
pub memory_layout: Option<MemoryLayoutHoverConfig>,
3131
pub documentation: bool,
3232
pub keywords: bool,
3333
pub format: HoverDocFormat,
3434
}
3535

36+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
37+
pub struct MemoryLayoutHoverConfig {
38+
pub size: Option<MemoryLayoutHoverRenderKind>,
39+
pub offset: Option<MemoryLayoutHoverRenderKind>,
40+
pub alignment: Option<MemoryLayoutHoverRenderKind>,
41+
pub niches: bool,
42+
}
43+
44+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
45+
pub enum MemoryLayoutHoverRenderKind {
46+
Decimal,
47+
Hexadecimal,
48+
Both,
49+
}
50+
3651
#[derive(Clone, Debug, PartialEq, Eq)]
3752
pub enum HoverDocFormat {
3853
Markdown,

0 commit comments

Comments
 (0)