about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 c383e6d3466..693c0494dbd 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 64f97452769..b1583c9d00b 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 d9d4a1a9921..4cbe7cca5af 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 ca6c169348d..4e171867fbf 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 db98bf2f9bc..9f493449249 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 6d6c9af7f04..7f4838888bd 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