Render niches on hover

This commit is contained in:
Lukas Wirth 2023-05-26 17:04:22 +02:00
parent bc8295255c
commit 3514f2f2ab
3 changed files with 33 additions and 13 deletions

View file

@ -62,7 +62,7 @@ use hir_ty::{
consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
diagnostics::BodyValidationDiagnostic, diagnostics::BodyValidationDiagnostic,
display::HexifiedConst, display::HexifiedConst,
layout::{Layout, LayoutError, RustcEnumVariantIdx, TagEncoding}, layout::{LayoutError, RustcEnumVariantIdx, TagEncoding},
method_resolution::{self, TyFingerprint}, method_resolution::{self, TyFingerprint},
mir::{self, interpret_mir}, mir::{self, interpret_mir},
primitive::UintTy, primitive::UintTy,
@ -133,8 +133,11 @@ pub use {
}, },
hir_ty::{ hir_ty::{
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
// FIXME: This just needs a HIR wrapper
layout::Layout,
mir::MirEvalError, mir::MirEvalError,
PointerCast, Safety, PointerCast,
Safety,
}, },
}; };
@ -4506,6 +4509,12 @@ impl HasCrate for Union {
} }
} }
impl HasCrate for Enum {
fn krate(&self, db: &dyn HirDatabase) -> Crate {
self.module(db).krate()
}
}
impl HasCrate for Field { impl HasCrate for Field {
fn krate(&self, db: &dyn HirDatabase) -> Crate { fn krate(&self, db: &dyn HirDatabase) -> Crate {
self.parent_def(db).module(db).krate() self.parent_def(db).module(db).krate()

View file

@ -3,8 +3,8 @@ use std::fmt::Display;
use either::Either; use either::Either;
use hir::{ use hir::{
Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasSource, HirDisplay, Semantics, db::HirDatabase, Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasCrate,
TypeInfo, HasSource, HirDisplay, Layout, Semantics, TypeInfo,
}; };
use ide_db::{ use ide_db::{
base_db::SourceDatabase, base_db::SourceDatabase,
@ -404,8 +404,9 @@ pub(super) fn definition(
.map(|layout| format!(", offset = {:#X}", layout.fields.offset(id).bytes())), .map(|layout| format!(", offset = {:#X}", layout.fields.offset(id).bytes())),
_ => None, _ => None,
}; };
let niches = niches(db, it, &layout).unwrap_or_default();
Some(format!( Some(format!(
"size = {:#X}, align = {:#X}{}", "size = {:#X}, align = {:#X}{}{niches}",
layout.size.bytes(), layout.size.bytes(),
layout.align.abi.bytes(), layout.align.abi.bytes(),
offset.as_deref().unwrap_or_default() offset.as_deref().unwrap_or_default()
@ -415,8 +416,9 @@ pub(super) fn definition(
Definition::Function(it) => label_and_docs(db, it), Definition::Function(it) => label_and_docs(db, it),
Definition::Adt(it) => label_and_layout_info_and_docs(db, it, config, |&it| { Definition::Adt(it) => label_and_layout_info_and_docs(db, it, config, |&it| {
let layout = it.layout(db).ok()?; let layout = it.layout(db).ok()?;
let niches = niches(db, it, &layout).unwrap_or_default();
Some(format!( Some(format!(
"size = {:#X}, align = {:#X}", "size = {:#X}, align = {:#X}{niches}",
layout.size.bytes(), layout.size.bytes(),
layout.align.abi.bytes() layout.align.abi.bytes()
)) ))
@ -437,14 +439,15 @@ pub(super) fn definition(
None None
} }
}, },
|it| { |&it| {
let (layout, tag_size) = it.layout(db).ok()?; let (layout, tag_size) = it.layout(db).ok()?;
let size = layout.size.bytes_usize() - tag_size; let size = layout.size.bytes_usize() - tag_size;
if size == 0 { if size == 0 {
// There is no value in showing layout info for fieldless variants // There is no value in showing layout info for fieldless variants
return None; return None;
} }
Some(format!("size = {:#X}", layout.size.bytes())) let niches = niches(db, it, &layout).unwrap_or_default();
Some(format!("size = {:#X}{niches}", layout.size.bytes()))
}, },
), ),
Definition::Const(it) => label_value_and_docs(db, it, |it| { Definition::Const(it) => label_value_and_docs(db, it, |it| {
@ -473,10 +476,11 @@ pub(super) fn definition(
Definition::TraitAlias(it) => label_and_docs(db, it), Definition::TraitAlias(it) => label_and_docs(db, it),
Definition::TypeAlias(it) => label_and_layout_info_and_docs(db, it, config, |&it| { Definition::TypeAlias(it) => label_and_layout_info_and_docs(db, it, config, |&it| {
let layout = it.ty(db).layout(db).ok()?; let layout = it.ty(db).layout(db).ok()?;
let niches = niches(db, it, &layout).unwrap_or_default();
Some(format!( Some(format!(
"size = {:#X}, align = {:#X}", "size = {:#X}, align = {:#X}{niches}",
layout.size.bytes(), layout.size.bytes(),
layout.align.abi.bytes() layout.align.abi.bytes(),
)) ))
}), }),
Definition::BuiltinType(it) => { Definition::BuiltinType(it) => {
@ -513,6 +517,13 @@ pub(super) fn definition(
markup(docs, label, mod_path) markup(docs, label, mod_path)
} }
fn niches(db: &RootDatabase, it: impl HasCrate, layout: &Layout) -> Option<String> {
Some(format!(
", niches = {}",
layout.largest_niche?.available(&*db.target_data_layout(it.krate(db).into())?)
))
}
fn type_info( fn type_info(
sema: &Semantics<'_, RootDatabase>, sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig, config: &HoverConfig,

View file

@ -1528,7 +1528,7 @@ fn test_hover_function_pointer_show_identifiers() {
``` ```
```rust ```rust
type foo = fn(a: i32, b: i32) -> i32 // size = 0x8, align = 0x8 type foo = fn(a: i32, b: i32) -> i32 // size = 0x8, align = 0x8, niches = 1
``` ```
"#]], "#]],
); );
@ -1546,7 +1546,7 @@ fn test_hover_function_pointer_no_identifier() {
``` ```
```rust ```rust
type foo = fn(i32, i32) -> i32 // size = 0x8, align = 0x8 type foo = fn(i32, i32) -> i32 // size = 0x8, align = 0x8, niches = 1
``` ```
"#]], "#]],
); );
@ -1904,7 +1904,7 @@ fn test_hover_layout_of_enum() {
``` ```
```rust ```rust
enum Foo // size = 0x10, align = 0x8 enum Foo // size = 0x10, align = 0x8, niches = 254
``` ```
"#]], "#]],
); );