Repository: rust-lang/rust-analyzer
Pull request #13745 (2022-12-09 09:10:41)

Show type info on hover of enum variant fields
Small addition to https://github.com/rust-lang/rust-analyzer/pull/13490


Patch:
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 3c6489fa97..f4f3c723ab 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -3,8 +3,13 @@
 use std::sync::Arc;
 
 use chalk_ir::{AdtId, TyKind};
-pub(self) use hir_def::layout::*;
-use hir_def::LocalFieldId;
+use hir_def::{
+    layout::{
+        Abi, FieldsShape, Integer, Layout, LayoutCalculator, LayoutError, Primitive, ReprOptions,
+        RustcEnumVariantIdx, Scalar, Size, StructKind, TargetDataLayout, Variants, WrappingRange,
+    },
+    LocalFieldId,
+};
 use stdx::never;
 
 use crate::{db::HirDatabase, Interner, Substitution, Ty};
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index d9791a4b63..e938295535 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -8,7 +8,7 @@ use hir_def::{
     AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
 };
 use la_arena::RawIdx;
-use rustc_index::vec::IndexVec;
+use smallvec::SmallVec;
 
 use crate::{db::HirDatabase, lang_items::is_unsafe_cell, layout::field_ty, Substitution};
 
@@ -34,13 +34,13 @@ pub fn layout_of_adt_query(
     let (variants, is_enum, is_union, repr) = match def {
         AdtId::StructId(s) => {
             let data = db.struct_data(s);
-            let mut r = IndexVec::new();
+            let mut r = SmallVec::<[_; 1]>::new();
             r.push(handle_variant(s.into(), &data.variant_data)?);
             (r, false, false, data.repr.unwrap_or_default())
         }
         AdtId::UnionId(id) => {
             let data = db.union_data(id);
-            let mut r = IndexVec::new();
+            let mut r = SmallVec::new();
             r.push(handle_variant(id.into(), &data.variant_data)?);
             (r, false, true, data.repr.unwrap_or_default())
         }
@@ -55,11 +55,12 @@ pub fn layout_of_adt_query(
                         &v.variant_data,
                     )
                 })
-                .collect::<Result<IndexVec<RustcEnumVariantIdx, _>, _>>()?;
+                .collect::<Result<SmallVec<_>, _>>()?;
             (r, true, false, data.repr.unwrap_or_default())
         }
     };
-    let variants = variants.iter().map(|x| x.iter().collect::<Vec<_>>()).collect::<Vec<_>>();
+    let variants =
+        variants.iter().map(|x| x.iter().collect::<Vec<_>>()).collect::<SmallVec<[_; 1]>>();
     let variants = variants.iter().map(|x| x.iter().collect()).collect();
     if is_union {
         cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)
diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs
index b76274bb85..b248031f15 100644
--- a/crates/hir-ty/src/layout/target.rs
+++ b/crates/hir-ty/src/layout/target.rs
@@ -6,7 +6,7 @@ use hir_def::layout::TargetDataLayout;
 
 use crate::db::HirDatabase;
 
-use super::{AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size};
+use hir_def::layout::{AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size};
 
 pub fn current_target_data_layout_query(db: &dyn HirDatabase) -> Arc<TargetDataLayout> {
     let crate_graph = db.crate_graph();
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index f37c9f4a6d..ef434e51c1 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -395,17 +395,17 @@ pub(super) fn definition(
             let id = it.index();
             let layout = it.layout(db).ok()?;
             let offset = match var_def {
-                hir::VariantDef::Struct(s) => {
-                    let layout = Adt::from(s).layout(db).ok()?;
-                    layout.fields.offset(id)
-                }
-                _ => return None,
+                hir::VariantDef::Struct(s) => Adt::from(s)
+                    .layout(db)
+                    .ok()
+                    .map(|layout| format!(", offset = {}", layout.fields.offset(id).bytes())),
+                _ => None,
             };
             Some(format!(
-                "size = {}, align = {}, offset = {}",
+                "size = {}, align = {}{}",
                 layout.size.bytes(),
                 layout.align.abi.bytes(),
-                offset.bytes()
+                offset.as_deref().unwrap_or_default()
             ))
         }),
         Definition::Module(it) => label_and_docs(db, it),


Test patch:
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index f82fd6d028..34dd7fb621 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -5176,6 +5176,28 @@ enum Enum {
     );
 }
 
+#[test]
+fn hover_record_variant_field() {
+    check(
+        r#"
+enum Enum {
+    RecordV { field$0: u32 }
+}
+"#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            test::RecordV
+            ```
+
+            ```rust
+            field: u32 // size = 4, align = 4
+            ```
+        "#]],
+    );
+}
+
 #[test]
 fn hover_trait_impl_assoc_item_def_doc_forwarding() {
     check(