Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/display.rs')
| -rw-r--r-- | crates/hir-ty/src/display.rs | 134 |
1 files changed, 122 insertions, 12 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index b22064d8c4..b6165f629e 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -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; |