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 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 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 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 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 return Err(LayoutError::HasPlaceholder), - }) + }; + Ok(layout) } fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result { 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( db: &RootDatabase, def: D, config: &HoverConfig, - value_extractor: E, + layout_extractor: E, ) -> (String, Option) where D: HasAttrs + HirDisplay, E: Fn(&D) -> Option, 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( +fn label_value_and_layout_info_and_docs( db: &RootDatabase, def: D, config: &HoverConfig, value_extractor: E, + layout_extractor: E2, ) -> (String, Option) where D: HasAttrs + HirDisplay, - E: Fn(&D) -> (Option, Option), + E: Fn(&D) -> Option, + E2: Fn(&D) -> Option, 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; 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; + // endregion:phantom_data } // region:default