mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
Don't leak rustc Layout in hir layer
This commit is contained in:
parent
3514f2f2ab
commit
1275adc200
2 changed files with 54 additions and 44 deletions
|
@ -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::{LayoutError, RustcEnumVariantIdx, TagEncoding},
|
layout::{Layout as TyLayout, LayoutError, RustcEnumVariantIdx, TagEncoding},
|
||||||
method_resolution::{self, TyFingerprint},
|
method_resolution::{self, TyFingerprint},
|
||||||
mir::{self, interpret_mir},
|
mir::{self, interpret_mir},
|
||||||
primitive::UintTy,
|
primitive::UintTy,
|
||||||
|
@ -133,11 +133,8 @@ 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,
|
PointerCast, Safety,
|
||||||
Safety,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -964,8 +961,8 @@ impl Field {
|
||||||
Type::new(db, var_id, ty)
|
Type::new(db, var_id, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Arc<Layout>, LayoutError> {
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||||
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
|
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into()).map(Layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
||||||
|
@ -1138,10 +1135,10 @@ impl Enum {
|
||||||
self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
|
self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(self, db: &dyn HirDatabase) -> Result<(Arc<Layout>, usize), LayoutError> {
|
pub fn layout(self, db: &dyn HirDatabase) -> Result<(Layout, usize), LayoutError> {
|
||||||
let layout = Adt::from(self).layout(db)?;
|
let layout = Adt::from(self).layout(db)?;
|
||||||
let tag_size =
|
let tag_size =
|
||||||
if let layout::Variants::Multiple { tag, tag_encoding, .. } = &layout.variants {
|
if let layout::Variants::Multiple { tag, tag_encoding, .. } = &layout.0.variants {
|
||||||
match tag_encoding {
|
match tag_encoding {
|
||||||
TagEncoding::Direct => {
|
TagEncoding::Direct => {
|
||||||
let target_data_layout = db
|
let target_data_layout = db
|
||||||
|
@ -1222,11 +1219,11 @@ impl Variant {
|
||||||
let parent_enum = self.parent_enum(db);
|
let parent_enum = self.parent_enum(db);
|
||||||
let (parent_layout, tag_size) = parent_enum.layout(db)?;
|
let (parent_layout, tag_size) = parent_enum.layout(db)?;
|
||||||
Ok((
|
Ok((
|
||||||
match &parent_layout.variants {
|
match &parent_layout.0.variants {
|
||||||
layout::Variants::Multiple { variants, .. } => {
|
layout::Variants::Multiple { variants, .. } => {
|
||||||
variants[RustcEnumVariantIdx(self.id)].clone()
|
Layout(Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()))
|
||||||
}
|
}
|
||||||
_ => (*parent_layout).clone(),
|
_ => parent_layout,
|
||||||
},
|
},
|
||||||
tag_size,
|
tag_size,
|
||||||
))
|
))
|
||||||
|
@ -1258,11 +1255,11 @@ impl Adt {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(self, db: &dyn HirDatabase) -> Result<Arc<Layout>, LayoutError> {
|
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||||
if db.generic_params(self.into()).iter().count() != 0 {
|
if db.generic_params(self.into()).iter().count() != 0 {
|
||||||
return Err(LayoutError::HasPlaceholder);
|
return Err(LayoutError::HasPlaceholder);
|
||||||
}
|
}
|
||||||
db.layout_of_adt(self.into(), Substitution::empty(Interner), self.krate(db).id)
|
db.layout_of_adt(self.into(), Substitution::empty(Interner), self.krate(db).id).map(Layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
||||||
|
@ -4246,8 +4243,8 @@ impl Type {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Arc<Layout>, LayoutError> {
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||||
db.layout_of_ty(self.ty.clone(), self.env.krate)
|
db.layout_of_ty(self.ty.clone(), self.env.krate).map(Layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4358,6 +4355,35 @@ fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::Closu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct Layout(Arc<TyLayout>);
|
||||||
|
|
||||||
|
impl Layout {
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
self.0.size.bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align(&self) -> u64 {
|
||||||
|
self.0.align.abi.bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn niches(&self, db: &dyn HirDatabase, krate: Crate) -> Option<u128> {
|
||||||
|
Some(self.0.largest_niche?.available(&*db.target_data_layout(krate.id)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field_offset(&self, idx: usize) -> Option<u64> {
|
||||||
|
match self.0.fields {
|
||||||
|
layout::FieldsShape::Primitive => None,
|
||||||
|
layout::FieldsShape::Union(_) => Some(0),
|
||||||
|
layout::FieldsShape::Array { stride, count } => {
|
||||||
|
let i = u64::try_from(idx).ok()?;
|
||||||
|
(i < count).then_some((stride * i).bytes())
|
||||||
|
}
|
||||||
|
layout::FieldsShape::Arbitrary { ref offsets, .. } => Some(offsets.get(idx)?.bytes()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum BindingMode {
|
pub enum BindingMode {
|
||||||
Move,
|
Move,
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::fmt::Display;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{
|
use hir::{
|
||||||
db::HirDatabase, Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasCrate,
|
Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasCrate, HasSource, HirDisplay,
|
||||||
HasSource, HirDisplay, Layout, Semantics, TypeInfo,
|
Layout, Semantics, TypeInfo,
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::SourceDatabase,
|
base_db::SourceDatabase,
|
||||||
|
@ -401,14 +401,14 @@ pub(super) fn definition(
|
||||||
hir::VariantDef::Struct(s) => Adt::from(s)
|
hir::VariantDef::Struct(s) => Adt::from(s)
|
||||||
.layout(db)
|
.layout(db)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|layout| format!(", offset = {:#X}", layout.fields.offset(id).bytes())),
|
.and_then(|layout| Some(format!(", offset = {:#X}", layout.field_offset(id)?))),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let niches = niches(db, it, &layout).unwrap_or_default();
|
let niches = niches(db, it, &layout).unwrap_or_default();
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"size = {:#X}, align = {:#X}{}{niches}",
|
"size = {:#X}, align = {:#X}{}{niches}",
|
||||||
layout.size.bytes(),
|
layout.size(),
|
||||||
layout.align.abi.bytes(),
|
layout.align(),
|
||||||
offset.as_deref().unwrap_or_default()
|
offset.as_deref().unwrap_or_default()
|
||||||
))
|
))
|
||||||
}),
|
}),
|
||||||
|
@ -417,11 +417,7 @@ pub(super) fn definition(
|
||||||
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();
|
let niches = niches(db, it, &layout).unwrap_or_default();
|
||||||
Some(format!(
|
Some(format!("size = {:#X}, align = {:#X}{niches}", layout.size(), layout.align()))
|
||||||
"size = {:#X}, align = {:#X}{niches}",
|
|
||||||
layout.size.bytes(),
|
|
||||||
layout.align.abi.bytes()
|
|
||||||
))
|
|
||||||
}),
|
}),
|
||||||
Definition::Variant(it) => label_value_and_layout_info_and_docs(
|
Definition::Variant(it) => label_value_and_layout_info_and_docs(
|
||||||
db,
|
db,
|
||||||
|
@ -441,13 +437,13 @@ pub(super) fn definition(
|
||||||
},
|
},
|
||||||
|&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() as 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;
|
||||||
}
|
}
|
||||||
let niches = niches(db, it, &layout).unwrap_or_default();
|
let niches = niches(db, it, &layout).unwrap_or_default();
|
||||||
Some(format!("size = {:#X}{niches}", layout.size.bytes()))
|
Some(format!("size = {:#X}{niches}", layout.size()))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Definition::Const(it) => label_value_and_docs(db, it, |it| {
|
Definition::Const(it) => label_value_and_docs(db, it, |it| {
|
||||||
|
@ -477,11 +473,7 @@ pub(super) fn definition(
|
||||||
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();
|
let niches = niches(db, it, &layout).unwrap_or_default();
|
||||||
Some(format!(
|
Some(format!("size = {:#X}, align = {:#X}{niches}", layout.size(), layout.align(),))
|
||||||
"size = {:#X}, align = {:#X}{niches}",
|
|
||||||
layout.size.bytes(),
|
|
||||||
layout.align.abi.bytes(),
|
|
||||||
))
|
|
||||||
}),
|
}),
|
||||||
Definition::BuiltinType(it) => {
|
Definition::BuiltinType(it) => {
|
||||||
return famous_defs
|
return famous_defs
|
||||||
|
@ -518,10 +510,7 @@ pub(super) fn definition(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn niches(db: &RootDatabase, it: impl HasCrate, layout: &Layout) -> Option<String> {
|
fn niches(db: &RootDatabase, it: impl HasCrate, layout: &Layout) -> Option<String> {
|
||||||
Some(format!(
|
Some(format!(", niches = {}", layout.niches(db, it.krate(db).into())?))
|
||||||
", niches = {}",
|
|
||||||
layout.largest_niche?.available(&*db.target_data_layout(it.krate(db).into())?)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_info(
|
fn type_info(
|
||||||
|
@ -571,7 +560,7 @@ fn closure_ty(
|
||||||
let layout = if config.memory_layout {
|
let layout = if config.memory_layout {
|
||||||
original
|
original
|
||||||
.layout(sema.db)
|
.layout(sema.db)
|
||||||
.map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
|
.map(|x| format!(" // size = {}, align = {}", x.size(), x.align()))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
} else {
|
} else {
|
||||||
String::default()
|
String::default()
|
||||||
|
@ -782,12 +771,7 @@ fn local(db: &RootDatabase, it: hir::Local, config: &HoverConfig) -> Option<Mark
|
||||||
};
|
};
|
||||||
if config.memory_layout {
|
if config.memory_layout {
|
||||||
if let Ok(layout) = it.ty(db).layout(db) {
|
if let Ok(layout) = it.ty(db).layout(db) {
|
||||||
format_to!(
|
format_to!(desc, " // size = {}, align = {}", layout.size(), layout.align());
|
||||||
desc,
|
|
||||||
" // size = {}, align = {}",
|
|
||||||
layout.size.bytes(),
|
|
||||||
layout.align.abi.bytes()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
markup(None, desc, None)
|
markup(None, desc, None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue