mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
beginning of MIR
This commit is contained in:
parent
b881deb66a
commit
cd67589f63
41 changed files with 4452 additions and 702 deletions
|
@ -7,6 +7,7 @@ use std::fmt::{self, Debug};
|
|||
use base_db::CrateId;
|
||||
use chalk_ir::BoundVar;
|
||||
use hir_def::{
|
||||
adt::VariantData,
|
||||
body,
|
||||
db::DefDatabase,
|
||||
find_path,
|
||||
|
@ -14,9 +15,9 @@ use hir_def::{
|
|||
item_scope::ItemInNs,
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
path::{Path, PathKind},
|
||||
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
|
||||
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
|
||||
visibility::Visibility,
|
||||
HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||
HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||
};
|
||||
use hir_expand::{hygiene::Hygiene, name::Name};
|
||||
use intern::{Internable, Interned};
|
||||
|
@ -25,14 +26,17 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
|
||||
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
|
||||
layout::layout_of_ty,
|
||||
lt_from_placeholder_idx,
|
||||
mapping::from_chalk,
|
||||
mir::pad16,
|
||||
primitive, to_assoc_type_id,
|
||||
utils::{self, generics},
|
||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstValue, DomainGoal,
|
||||
GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability,
|
||||
OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, Substitution, TraitRef,
|
||||
TraitRefExt, Ty, TyExt, TyKind, WhereClause,
|
||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
|
||||
DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
|
||||
MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
|
||||
Substitution, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
pub trait HirWrite: fmt::Write {
|
||||
|
@ -362,20 +366,125 @@ impl HirDisplay for GenericArg {
|
|||
impl HirDisplay for Const {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
let data = self.interned();
|
||||
match data.value {
|
||||
match &data.value {
|
||||
ConstValue::BoundVar(idx) => idx.hir_fmt(f),
|
||||
ConstValue::InferenceVar(..) => write!(f, "#c#"),
|
||||
ConstValue::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(f.db, idx);
|
||||
let id = from_placeholder_idx(f.db, *idx);
|
||||
let generics = generics(f.db.upcast(), id.parent);
|
||||
let param_data = &generics.params.type_or_consts[id.local_id];
|
||||
write!(f, "{}", param_data.name().unwrap())
|
||||
}
|
||||
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
|
||||
ConstValue::Concrete(c) => match &c.interned {
|
||||
ConstScalar::Bytes(b, m) => render_const_scalar(f, &b, m, &data.ty),
|
||||
ConstScalar::Unknown => f.write_char('_'),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_const_scalar(
|
||||
f: &mut HirFormatter<'_>,
|
||||
b: &[u8],
|
||||
memory_map: &MemoryMap,
|
||||
ty: &Ty,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match ty.kind(Interner) {
|
||||
chalk_ir::TyKind::Scalar(s) => match s {
|
||||
Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
|
||||
Scalar::Char => {
|
||||
let x = u128::from_le_bytes(pad16(b, false)) as u32;
|
||||
let Ok(c) = char::try_from(x) else {
|
||||
return f.write_str("<unicode-error>");
|
||||
};
|
||||
write!(f, "{c:?}")
|
||||
}
|
||||
Scalar::Int(_) => {
|
||||
let x = i128::from_le_bytes(pad16(b, true));
|
||||
write!(f, "{x}")
|
||||
}
|
||||
Scalar::Uint(_) => {
|
||||
let x = u128::from_le_bytes(pad16(b, false));
|
||||
write!(f, "{x}")
|
||||
}
|
||||
Scalar::Float(fl) => match fl {
|
||||
chalk_ir::FloatTy::F32 => {
|
||||
let x = f32::from_le_bytes(b.try_into().unwrap());
|
||||
write!(f, "{x:?}")
|
||||
}
|
||||
chalk_ir::FloatTy::F64 => {
|
||||
let x = f64::from_le_bytes(b.try_into().unwrap());
|
||||
write!(f, "{x:?}")
|
||||
}
|
||||
},
|
||||
},
|
||||
chalk_ir::TyKind::Ref(_, _, t) => match t.kind(Interner) {
|
||||
chalk_ir::TyKind::Str => {
|
||||
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
||||
let bytes = memory_map.0.get(&addr).map(|x| &**x).unwrap_or(&[]);
|
||||
let s = std::str::from_utf8(bytes).unwrap_or("<utf8-error>");
|
||||
write!(f, "{s:?}")
|
||||
}
|
||||
_ => f.write_str("<error>"),
|
||||
},
|
||||
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
|
||||
hir_def::AdtId::StructId(s) => {
|
||||
let data = f.db.struct_data(s);
|
||||
let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone()) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
match data.variant_data.as_ref() {
|
||||
VariantData::Record(fields) | VariantData::Tuple(fields) => {
|
||||
let field_types = f.db.field_types(s.into());
|
||||
let krate = adt.0.module(f.db.upcast()).krate();
|
||||
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
|
||||
let offset = layout
|
||||
.fields
|
||||
.offset(u32::from(id.into_raw()) as usize)
|
||||
.bytes_usize();
|
||||
let ty = field_types[id].clone().substitute(Interner, subst);
|
||||
let Ok(layout) = layout_of_ty(f.db, &ty, krate) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size = layout.size.bytes_usize();
|
||||
render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)
|
||||
};
|
||||
let mut it = fields.iter();
|
||||
if matches!(data.variant_data.as_ref(), VariantData::Record(_)) {
|
||||
write!(f, "{} {{", data.name)?;
|
||||
if let Some((id, data)) = it.next() {
|
||||
write!(f, " {}: ", data.name)?;
|
||||
render_field(f, id)?;
|
||||
}
|
||||
for (id, data) in it {
|
||||
write!(f, ", {}: ", data.name)?;
|
||||
render_field(f, id)?;
|
||||
}
|
||||
write!(f, " }}")?;
|
||||
} else {
|
||||
let mut it = it.map(|x| x.0);
|
||||
write!(f, "{}(", data.name)?;
|
||||
if let Some(id) = it.next() {
|
||||
render_field(f, id)?;
|
||||
}
|
||||
for id in it {
|
||||
write!(f, ", ")?;
|
||||
render_field(f, id)?;
|
||||
}
|
||||
write!(f, ")")?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
VariantData::Unit => write!(f, "{}", data.name),
|
||||
}
|
||||
}
|
||||
hir_def::AdtId::UnionId(u) => write!(f, "{}", f.db.union_data(u).name),
|
||||
hir_def::AdtId::EnumId(_) => f.write_str("<enum-not-supported>"),
|
||||
},
|
||||
_ => f.write_str("<error>"),
|
||||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for BoundVar {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
write!(f, "?{}.{}", self.debruijn.depth(), self.index)
|
||||
|
@ -614,8 +723,9 @@ impl HirDisplay for Ty {
|
|||
{
|
||||
return true;
|
||||
}
|
||||
if let Some(ConstValue::Concrete(c)) =
|
||||
parameter.constant(Interner).map(|x| x.data(Interner).value)
|
||||
if let Some(ConstValue::Concrete(c)) = parameter
|
||||
.constant(Interner)
|
||||
.map(|x| &x.data(Interner).value)
|
||||
{
|
||||
if c.interned == ConstScalar::Unknown {
|
||||
return true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue