Unnamed repository; edit this file 'description' to name the repository.
Render size, align and offset hover values in hex
Lukas Wirth 2023-05-26
parent eee6872 · commit be9cc0b
-rw-r--r--crates/hir-ty/src/layout.rs35
-rw-r--r--crates/hir/src/lib.rs44
-rw-r--r--crates/ide/src/hover/render.rs75
-rw-r--r--crates/ide/src/hover/tests.rs103
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs12
-rw-r--r--crates/test-utils/src/minicore.rs6
6 files changed, 165 insertions, 110 deletions
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index c383e6d346..693c0494db 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -1,7 +1,7 @@
//! Compute the binary representation of a type
use base_db::CrateId;
-use chalk_ir::{AdtId, TyKind};
+use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
use hir_def::{
layout::{
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
@@ -83,7 +83,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
let dl = &*cx.current_data_layout();
let trait_env = Arc::new(TraitEnvironment::empty(krate));
let ty = normalize(db, trait_env, ty.clone());
- Ok(match ty.kind(Interner) {
+ let layout = match ty.kind(Interner) {
TyKind::Adt(AdtId(def), subst) => db.layout_of_adt(*def, subst.clone(), krate)?,
TyKind::Scalar(s) => match s {
chalk_ir::Scalar::Bool => Layout::scalar(
@@ -104,12 +104,12 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
dl,
Primitive::Int(
match i {
- chalk_ir::IntTy::Isize => dl.ptr_sized_integer(),
- chalk_ir::IntTy::I8 => Integer::I8,
- chalk_ir::IntTy::I16 => Integer::I16,
- chalk_ir::IntTy::I32 => Integer::I32,
- chalk_ir::IntTy::I64 => Integer::I64,
- chalk_ir::IntTy::I128 => Integer::I128,
+ IntTy::Isize => dl.ptr_sized_integer(),
+ IntTy::I8 => Integer::I8,
+ IntTy::I16 => Integer::I16,
+ IntTy::I32 => Integer::I32,
+ IntTy::I64 => Integer::I64,
+ IntTy::I128 => Integer::I128,
},
true,
),
@@ -118,12 +118,12 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
dl,
Primitive::Int(
match i {
- chalk_ir::UintTy::Usize => dl.ptr_sized_integer(),
- chalk_ir::UintTy::U8 => Integer::I8,
- chalk_ir::UintTy::U16 => Integer::I16,
- chalk_ir::UintTy::U32 => Integer::I32,
- chalk_ir::UintTy::U64 => Integer::I64,
- chalk_ir::UintTy::U128 => Integer::I128,
+ UintTy::Usize => dl.ptr_sized_integer(),
+ UintTy::U8 => Integer::I8,
+ UintTy::U16 => Integer::I16,
+ UintTy::U32 => Integer::I32,
+ UintTy::U64 => Integer::I64,
+ UintTy::U128 => Integer::I128,
},
false,
),
@@ -131,8 +131,8 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
chalk_ir::Scalar::Float(f) => scalar(
dl,
match f {
- chalk_ir::FloatTy::F32 => Primitive::F32,
- chalk_ir::FloatTy::F64 => Primitive::F64,
+ FloatTy::F32 => Primitive::F32,
+ FloatTy::F64 => Primitive::F64,
},
),
},
@@ -283,7 +283,8 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
| TyKind::Placeholder(_)
| TyKind::BoundVar(_)
| TyKind::InferenceVar(_, _) => return Err(LayoutError::HasPlaceholder),
- })
+ };
+ Ok(layout)
}
fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 64f9745276..b1583c9d00 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1125,6 +1125,25 @@ impl Enum {
pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
}
+
+ pub fn layout(self, db: &dyn HirDatabase) -> Result<(Layout, usize), LayoutError> {
+ let layout = Adt::from(self).layout(db)?;
+ let tag_size =
+ if let layout::Variants::Multiple { tag, tag_encoding, .. } = &layout.variants {
+ match tag_encoding {
+ TagEncoding::Direct => {
+ let target_data_layout = db
+ .target_data_layout(self.module(db).krate().id)
+ .ok_or(LayoutError::TargetLayoutNotAvailable)?;
+ tag.size(&*target_data_layout).bytes_usize()
+ }
+ TagEncoding::Niche { .. } => 0,
+ }
+ } else {
+ 0
+ };
+ Ok((layout, tag_size))
+ }
}
impl HasVisibility for Enum {
@@ -1185,23 +1204,16 @@ impl Variant {
/// Return layout of the variant and tag size of the parent enum.
pub fn layout(&self, db: &dyn HirDatabase) -> Result<(Layout, usize), LayoutError> {
let parent_enum = self.parent_enum(db);
- let parent_layout = Adt::from(parent_enum).layout(db)?;
- if let layout::Variants::Multiple { variants, tag, tag_encoding, tag_field: _ } =
- parent_layout.variants
- {
- let tag_size = match tag_encoding {
- TagEncoding::Direct => {
- let target_data_layout = db
- .target_data_layout(parent_enum.module(db).krate().id)
- .ok_or(LayoutError::TargetLayoutNotAvailable)?;
- tag.size(&*target_data_layout).bytes_usize()
+ let (parent_layout, tag_size) = parent_enum.layout(db)?;
+ Ok((
+ match parent_layout.variants {
+ layout::Variants::Multiple { variants, .. } => {
+ variants[RustcEnumVariantIdx(self.id)].clone()
}
- TagEncoding::Niche { .. } => 0,
- };
- Ok((variants[RustcEnumVariantIdx(self.id)].clone(), tag_size))
- } else {
- Ok((parent_layout, 0))
- }
+ _ => parent_layout,
+ },
+ tag_size,
+ ))
}
}
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index d9d4a1a992..4cbe7cca5a 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -401,11 +401,11 @@ pub(super) fn definition(
hir::VariantDef::Struct(s) => Adt::from(s)
.layout(db)
.ok()
- .map(|layout| format!(", offset = {}", layout.fields.offset(id).bytes())),
+ .map(|layout| format!(", offset = {:#X}", layout.fields.offset(id).bytes())),
_ => None,
};
Some(format!(
- "size = {}, align = {}{}",
+ "size = {:#X}, align = {:#X}{}",
layout.size.bytes(),
layout.align.abi.bytes(),
offset.as_deref().unwrap_or_default()
@@ -415,28 +415,38 @@ pub(super) fn definition(
Definition::Function(it) => label_and_docs(db, it),
Definition::Adt(it) => label_and_layout_info_and_docs(db, it, config, |&it| {
let layout = it.layout(db).ok()?;
- Some(format!("size = {}, align = {}", layout.size.bytes(), layout.align.abi.bytes()))
+ Some(format!(
+ "size = {:#X}, align = {:#X}",
+ layout.size.bytes(),
+ layout.align.abi.bytes()
+ ))
}),
- Definition::Variant(it) => label_value_and_layout_info_and_docs(db, it, config, |&it| {
- let layout = (|| {
+ Definition::Variant(it) => label_value_and_layout_info_and_docs(
+ db,
+ it,
+ config,
+ |&it| {
+ if !it.parent_enum(db).is_data_carrying(db) {
+ match it.eval(db) {
+ Ok(x) => {
+ Some(if x >= 10 { format!("{x} ({x:#X})") } else { format!("{x}") })
+ }
+ Err(_) => it.value(db).map(|x| format!("{x:?}")),
+ }
+ } else {
+ None
+ }
+ },
+ |it| {
let (layout, tag_size) = it.layout(db).ok()?;
let size = layout.size.bytes_usize() - tag_size;
if size == 0 {
// There is no value in showing layout info for fieldless variants
return None;
}
- Some(format!("size = {}", layout.size.bytes()))
- })();
- let value = if !it.parent_enum(db).is_data_carrying(db) {
- match it.eval(db) {
- Ok(x) => Some(if x >= 10 { format!("{x} ({x:#X})") } else { format!("{x}") }),
- Err(_) => it.value(db).map(|x| format!("{x:?}")),
- }
- } else {
- None
- };
- (value, layout)
- }),
+ Some(format!("size = {:#X}", layout.size.bytes()))
+ },
+ ),
Definition::Const(it) => label_value_and_docs(db, it, |it| {
let body = it.render_eval(db);
match body {
@@ -463,7 +473,11 @@ pub(super) fn definition(
Definition::TraitAlias(it) => label_and_docs(db, it),
Definition::TypeAlias(it) => label_and_layout_info_and_docs(db, it, config, |&it| {
let layout = it.ty(db).layout(db).ok()?;
- Some(format!("size = {}, align = {}", layout.size.bytes(), layout.align.abi.bytes()))
+ Some(format!(
+ "size = {:#X}, align = {:#X}",
+ layout.size.bytes(),
+ layout.align.abi.bytes()
+ ))
}),
Definition::BuiltinType(it) => {
return famous_defs
@@ -634,41 +648,42 @@ fn label_and_layout_info_and_docs<D, E, V>(
db: &RootDatabase,
def: D,
config: &HoverConfig,
- value_extractor: E,
+ layout_extractor: E,
) -> (String, Option<hir::Documentation>)
where
D: HasAttrs + HirDisplay,
E: Fn(&D) -> Option<V>,
V: Display,
{
- let label = match value_extractor(&def) {
- Some(value) if config.memory_layout => format!("{} // {value}", def.display(db)),
+ let label = match config.memory_layout.then(|| layout_extractor(&def)).flatten() {
+ Some(layout) => format!("{} // {layout}", def.display(db)),
_ => def.display(db).to_string(),
};
let docs = def.attrs(db).docs();
(label, docs)
}
-fn label_value_and_layout_info_and_docs<D, E, V, L>(
+fn label_value_and_layout_info_and_docs<D, E, E2, V, L>(
db: &RootDatabase,
def: D,
config: &HoverConfig,
value_extractor: E,
+ layout_extractor: E2,
) -> (String, Option<hir::Documentation>)
where
D: HasAttrs + HirDisplay,
- E: Fn(&D) -> (Option<V>, Option<L>),
+ E: Fn(&D) -> Option<V>,
+ E2: Fn(&D) -> Option<L>,
V: Display,
L: Display,
{
- let (value, layout) = value_extractor(&def);
- let label = if let Some(value) = value {
- format!("{} = {value}", def.display(db))
- } else {
- def.display(db).to_string()
+ let value = value_extractor(&def);
+ let label = match value {
+ Some(value) => format!("{} = {value}", def.display(db)),
+ None => def.display(db).to_string(),
};
- let label = match layout {
- Some(layout) if config.memory_layout => format!("{} // {layout}", label),
+ let label = match config.memory_layout.then(|| layout_extractor(&def)).flatten() {
+ Some(layout) => format!("{} // {layout}", label),
_ => label,
};
let docs = def.attrs(db).docs();
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index ca6c169348..4e171867fb 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -667,7 +667,7 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
```
```rust
- field_a: u8 // size = 1, align = 1, offset = 4
+ field_a: u8 // size = 0x1, align = 0x1, offset = 0x4
```
"#]],
);
@@ -692,7 +692,7 @@ fn main() {
```
```rust
- field_a: u32 // size = 4, align = 4, offset = 0
+ field_a: u32 // size = 0x4, align = 0x4, offset = 0x0
```
"#]],
);
@@ -714,7 +714,7 @@ fn main() {
```
```rust
- field_a: u32 // size = 4, align = 4, offset = 0
+ field_a: u32 // size = 0x4, align = 0x4, offset = 0x0
```
"#]],
);
@@ -1521,16 +1521,16 @@ fn test_hover_function_pointer_show_identifiers() {
check(
r#"type foo$0 = fn(a: i32, b: i32) -> i32;"#,
expect![[r#"
- *foo*
+ *foo*
- ```rust
- test
- ```
+ ```rust
+ test
+ ```
- ```rust
- type foo = fn(a: i32, b: i32) -> i32 // size = 8, align = 8
- ```
- "#]],
+ ```rust
+ type foo = fn(a: i32, b: i32) -> i32 // size = 0x8, align = 0x8
+ ```
+ "#]],
);
}
@@ -1539,16 +1539,16 @@ fn test_hover_function_pointer_no_identifier() {
check(
r#"type foo$0 = fn(i32, _: i32) -> i32;"#,
expect![[r#"
- *foo*
+ *foo*
- ```rust
- test
- ```
+ ```rust
+ test
+ ```
- ```rust
- type foo = fn(i32, i32) -> i32 // size = 8, align = 8
- ```
- "#]],
+ ```rust
+ type foo = fn(i32, i32) -> i32 // size = 0x8, align = 0x8
+ ```
+ "#]],
);
}
@@ -1674,7 +1674,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar // size = 0, align = 1
+ struct Bar // size = 0x0, align = 0x1
```
---
@@ -1710,7 +1710,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar // size = 0, align = 1
+ struct Bar // size = 0x0, align = 0x1
```
---
@@ -1739,7 +1739,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar // size = 0, align = 1
+ struct Bar // size = 0x0, align = 0x1
```
---
@@ -1767,7 +1767,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar // size = 0, align = 1
+ pub struct Bar // size = 0x0, align = 0x1
```
---
@@ -1794,7 +1794,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar // size = 0, align = 1
+ pub struct Bar // size = 0x0, align = 0x1
```
---
@@ -1883,7 +1883,28 @@ fn test_hover_layout_of_variant() {
```
```rust
- Variant1(u8, u16) // size = 4
+ Variant1(u8, u16) // size = 0x4
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn test_hover_layout_of_enum() {
+ check(
+ r#"enum $0Foo {
+ Variant1(u8, u16),
+ Variant2(i32, u8, i64),
+ }"#,
+ expect![[r#"
+ *Foo*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ enum Foo // size = 0x10, align = 0x8
```
"#]],
);
@@ -3192,7 +3213,7 @@ fn main() {
```
```rust
- f: i32 // size = 4, align = 4, offset = 0
+ f: i32 // size = 0x4, align = 0x4, offset = 0x0
```
"#]],
);
@@ -3730,16 +3751,16 @@ struct Foo<const LEN: usize>;
type Fo$0o2 = Foo<2>;
"#,
expect![[r#"
- *Foo2*
+ *Foo2*
- ```rust
- test
- ```
+ ```rust
+ test
+ ```
- ```rust
- type Foo2 = Foo<2> // size = 0, align = 1
- ```
- "#]],
+ ```rust
+ type Foo2 = Foo<2> // size = 0x0, align = 0x1
+ ```
+ "#]],
);
}
@@ -4648,7 +4669,7 @@ pub fn gimme() -> theitem::TheItem {
```
```rust
- pub struct TheItem // size = 0, align = 1
+ pub struct TheItem // size = 0x0, align = 0x1
```
---
@@ -4796,7 +4817,7 @@ mod string {
```
```rust
- struct String // size = 0, align = 1
+ struct String // size = 0x0, align = 0x1
```
---
@@ -5465,7 +5486,7 @@ foo_macro!(
```
```rust
- pub struct Foo // size = 0, align = 1
+ pub struct Foo // size = 0x0, align = 0x1
```
---
@@ -5490,7 +5511,7 @@ pub struct Foo(i32);
```
```rust
- pub struct Foo // size = 4, align = 4
+ pub struct Foo // size = 0x4, align = 0x4
```
---
@@ -5589,7 +5610,7 @@ enum Enum {
```
```rust
- RecordV { field: u32 } // size = 4
+ RecordV { field: u32 } // size = 0x4
```
"#]],
);
@@ -5611,7 +5632,7 @@ enum Enum {
```
```rust
- field: u32 // size = 4, align = 4
+ field: u32 // size = 0x4, align = 0x4
```
"#]],
);
@@ -6113,7 +6134,7 @@ fn test() {
```
```rust
- f: u32 // size = 4, align = 4, offset = 0
+ f: u32 // size = 0x4, align = 0x4, offset = 0x0
```
"#]],
);
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index db98bf2f9b..9f49344924 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -474,7 +474,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9164..9172,
+ range: 9165..9173,
},
),
tooltip: "",
@@ -487,7 +487,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9196..9200,
+ range: 9197..9201,
},
),
tooltip: "",
@@ -511,7 +511,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9164..9172,
+ range: 9165..9173,
},
),
tooltip: "",
@@ -524,7 +524,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9196..9200,
+ range: 9197..9201,
},
),
tooltip: "",
@@ -548,7 +548,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9164..9172,
+ range: 9165..9173,
},
),
tooltip: "",
@@ -561,7 +561,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9196..9200,
+ range: 9197..9201,
},
),
tooltip: "",
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 6d6c9af7f0..7f4838888b 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -38,6 +38,7 @@
//! option: panic
//! ord: eq, option
//! panic: fmt
+//! phantom_data:
//! pin:
//! range:
//! result:
@@ -119,6 +120,11 @@ pub mod marker {
#[lang = "tuple_trait"]
pub trait Tuple {}
// endregion:fn
+
+ // region:phantom_data
+ #[lang = "phantom_data"]
+ pub struct PhantomData<T: ?Sized>;
+ // endregion:phantom_data
}
// region:default