diff --git a/crates/hir-ty/src/consteval_nextsolver.rs b/crates/hir-ty/src/consteval_nextsolver.rs index da4aff54de..cdf861290a 100644 --- a/crates/hir-ty/src/consteval_nextsolver.rs +++ b/crates/hir-ty/src/consteval_nextsolver.rs @@ -132,9 +132,9 @@ pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option, krate: Cr ) } -pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option { +pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option { let interner = DbInterner::new_with(db, None, None); - match (*c).kind() { + match c.kind() { ConstKind::Param(_) => None, ConstKind::Infer(_) => None, ConstKind::Bound(_, _) => None, @@ -147,7 +147,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option< }; let subst = convert_args_for_result(interner, unevaluated_const.args.as_slice()); let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); - try_const_usize(db, &ec) + try_const_usize(db, ec) } ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().0, false))), ConstKind::Error(_) => None, @@ -212,7 +212,7 @@ pub(crate) fn const_eval_discriminant_variant( let c = if is_signed { try_const_isize(db, &c).unwrap() } else { - try_const_usize(db, &c).unwrap() as i128 + try_const_usize(db, c).unwrap() as i128 }; Ok(c) } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 8f35a3c214..9f87c37834 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -11,8 +11,8 @@ use base_db::Crate; use chalk_ir::{BoundVar, Safety, TyKind}; use either::Either; use hir_def::{ - GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, - ModuleId, TraitId, + GenericDefId, HasModule, ImportPathConfig, LocalFieldId, Lookup, ModuleDefId, ModuleId, + TraitId, db::DefDatabase, expr_store::{ExpressionStore, path::Path}, find_path::{self, PrefixKind}, @@ -37,26 +37,34 @@ use rustc_apfloat::{ ieee::{Half as f16, Quad as f128}, }; use rustc_hash::FxHashSet; +use rustc_type_ir::{ + AliasTyKind, + inherent::{AdtDef, IntoKind, SliceLike}, +}; use smallvec::SmallVec; use span::Edition; use stdx::never; use triomphe::Arc; use crate::{ - AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, - ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, - LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, - QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, - TyExt, WhereClause, - consteval::try_const_usize, + AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, ConstScalar, + ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, + LifetimeOutlives, MemoryMap, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, + TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, consteval_nextsolver, db::{HirDatabase, InternedClosure}, - from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, + from_assoc_type_id, from_placeholder_idx, generics::generics, infer::normalize, layout::Layout, lt_from_placeholder_idx, - mapping::from_chalk, mir::pad16, + next_solver::{ + BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId, + mapping::{ + ChalkToNextSolver, convert_args_for_result, convert_const_for_result, + convert_region_for_result, convert_ty_for_result, + }, + }, primitive, to_assoc_type_id, utils::{self, ClosureSubst, detect_variant_from_bytes}, }; @@ -185,6 +193,29 @@ impl HirFormatter<'_> { DisplayLifetime::Never => false, } } + + fn render_region(&self, lifetime: crate::next_solver::Region<'_>) -> bool { + match self.display_lifetimes { + DisplayLifetime::Always => true, + DisplayLifetime::OnlyStatic => { + matches!(lifetime.kind(), rustc_type_ir::RegionKind::ReStatic) + } + DisplayLifetime::OnlyNamed => { + matches!( + lifetime.kind(), + rustc_type_ir::RegionKind::RePlaceholder(_) + | rustc_type_ir::RegionKind::ReEarlyParam(_) + ) + } + DisplayLifetime::OnlyNamedOrStatic => matches!( + lifetime.kind(), + rustc_type_ir::RegionKind::ReStatic + | rustc_type_ir::RegionKind::RePlaceholder(_) + | rustc_type_ir::RegionKind::ReEarlyParam(_) + ), + DisplayLifetime::Never => false, + } + } } pub trait HirDisplay { @@ -476,10 +507,6 @@ impl DisplayKind { matches!(self, Self::SourceCode { .. }) } - fn is_test(self) -> bool { - matches!(self, Self::Test) - } - fn allows_opaque(self) -> bool { match self { Self::SourceCode { allow_opaque, .. } => allow_opaque, @@ -721,59 +748,87 @@ fn render_const_scalar( ty: &Ty, ) -> Result<(), HirDisplayError> { let trait_env = TraitEnvironment::empty(f.krate()); + let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block); let ty = normalize(f.db, trait_env.clone(), ty.clone()); - match ty.kind(Interner) { - TyKind::Scalar(s) => match s { - Scalar::Bool => write!(f, "{}", b[0] != 0), - Scalar::Char => { - let it = u128::from_le_bytes(pad16(b, false)) as u32; - let Ok(c) = char::try_from(it) else { - return f.write_str(""); - }; - write!(f, "{c:?}") + let ty = ty.to_nextsolver(interner); + render_const_scalar_inner(f, b, memory_map, ty, trait_env, interner) +} + +fn render_const_scalar_ns( + f: &mut HirFormatter<'_>, + b: &[u8], + memory_map: &MemoryMap, + ty: crate::next_solver::Ty<'_>, +) -> Result<(), HirDisplayError> { + let trait_env = TraitEnvironment::empty(f.krate()); + let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block); + let ty = crate::next_solver::project::solve_normalize::normalize( + interner, + trait_env.env.to_nextsolver(interner), + ty, + ); + render_const_scalar_inner(f, b, memory_map, ty, trait_env, interner) +} + +fn render_const_scalar_inner( + f: &mut HirFormatter<'_>, + b: &[u8], + memory_map: &MemoryMap, + ty: crate::next_solver::Ty<'_>, + trait_env: Arc, + interner: DbInterner<'_>, +) -> Result<(), HirDisplayError> { + use rustc_type_ir::TyKind; + match ty.kind() { + TyKind::Bool => write!(f, "{}", b[0] != 0), + TyKind::Char => { + let it = u128::from_le_bytes(pad16(b, false)) as u32; + let Ok(c) = char::try_from(it) else { + return f.write_str(""); + }; + write!(f, "{c:?}") + } + TyKind::Int(_) => { + let it = i128::from_le_bytes(pad16(b, true)); + write!(f, "{it}") + } + TyKind::Uint(_) => { + let it = u128::from_le_bytes(pad16(b, false)); + write!(f, "{it}") + } + TyKind::Float(fl) => match fl { + rustc_type_ir::FloatTy::F16 => { + // FIXME(#17451): Replace with builtins once they are stabilised. + let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into()); + let s = it.to_string(); + if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) { + // Match Rust debug formatting + write!(f, "{s}.0") + } else { + write!(f, "{s}") + } } - Scalar::Int(_) => { - let it = i128::from_le_bytes(pad16(b, true)); - write!(f, "{it}") + rustc_type_ir::FloatTy::F32 => { + let it = f32::from_le_bytes(b.try_into().unwrap()); + write!(f, "{it:?}") } - Scalar::Uint(_) => { - let it = u128::from_le_bytes(pad16(b, false)); - write!(f, "{it}") + rustc_type_ir::FloatTy::F64 => { + let it = f64::from_le_bytes(b.try_into().unwrap()); + write!(f, "{it:?}") } - Scalar::Float(fl) => match fl { - chalk_ir::FloatTy::F16 => { - // FIXME(#17451): Replace with builtins once they are stabilised. - let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into()); - let s = it.to_string(); - if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) { - // Match Rust debug formatting - write!(f, "{s}.0") - } else { - write!(f, "{s}") - } + rustc_type_ir::FloatTy::F128 => { + // FIXME(#17451): Replace with builtins once they are stabilised. + let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap())); + let s = it.to_string(); + if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) { + // Match Rust debug formatting + write!(f, "{s}.0") + } else { + write!(f, "{s}") } - chalk_ir::FloatTy::F32 => { - let it = f32::from_le_bytes(b.try_into().unwrap()); - write!(f, "{it:?}") - } - chalk_ir::FloatTy::F64 => { - let it = f64::from_le_bytes(b.try_into().unwrap()); - write!(f, "{it:?}") - } - chalk_ir::FloatTy::F128 => { - // FIXME(#17451): Replace with builtins once they are stabilised. - let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap())); - let s = it.to_string(); - if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) { - // Match Rust debug formatting - write!(f, "{s}.0") - } else { - write!(f, "{s}") - } - } - }, + } }, - TyKind::Ref(_, _, t) => match t.kind(Interner) { + TyKind::Ref(_, t, _) => match t.kind() { TyKind::Str => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); @@ -786,7 +841,7 @@ fn render_const_scalar( TyKind::Slice(ty) => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); - let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else { + let Ok(layout) = f.db.layout_of_ty_ns(ty, trait_env) else { return f.write_str(""); }; let size_one = layout.size.bytes_usize(); @@ -810,11 +865,11 @@ fn render_const_scalar( f.write_str(", ")?; } let offset = size_one * i; - render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, ty)?; + render_const_scalar_ns(f, &bytes[offset..offset + size_one], memory_map, ty)?; } f.write_str("]") } - TyKind::Dyn(_) => { + TyKind::Dynamic(_, _, _) => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); let Ok(t) = memory_map.vtable_ty(ty_id) else { @@ -828,15 +883,16 @@ fn render_const_scalar( return f.write_str(""); }; f.write_str("&")?; - render_const_scalar(f, bytes, memory_map, t) + render_const_scalar_ns(f, bytes, memory_map, t.to_nextsolver(interner)) } - TyKind::Adt(adt, _) if b.len() == 2 * size_of::() => match adt.0 { - hir_def::AdtId::StructId(s) => { + TyKind::Adt(adt, _) if b.len() == 2 * size_of::() => match adt.def_id() { + SolverDefId::AdtId(hir_def::AdtId::StructId(s)) => { let data = f.db.struct_signature(s); write!(f, "&{}", data.name.display(f.db, f.edition()))?; Ok(()) } - _ => f.write_str(""), + SolverDefId::AdtId(_) => f.write_str(""), + _ => unreachable!(), }, _ => { let addr = usize::from_le_bytes(match b.try_into() { @@ -850,7 +906,7 @@ fn render_const_scalar( return f.write_str(""); } }); - let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else { + let Ok(layout) = f.db.layout_of_ty_ns(t, trait_env) else { return f.write_str(""); }; let size = layout.size.bytes_usize(); @@ -858,37 +914,40 @@ fn render_const_scalar( return f.write_str(""); }; f.write_str("&")?; - render_const_scalar(f, bytes, memory_map, t) + render_const_scalar_ns(f, bytes, memory_map, t) } }, - TyKind::Tuple(_, subst) => { - let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { + TyKind::Tuple(tys) => { + let Ok(layout) = f.db.layout_of_ty_ns(ty, trait_env.clone()) else { return f.write_str(""); }; f.write_str("(")?; let mut first = true; - for (id, ty) in subst.iter(Interner).enumerate() { + for (id, ty) in tys.iter().enumerate() { if first { first = false; } else { f.write_str(", ")?; } - let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument let offset = layout.fields.offset(id).bytes_usize(); - let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { + let Ok(layout) = f.db.layout_of_ty_ns(ty, trait_env.clone()) else { f.write_str("")?; continue; }; let size = layout.size.bytes_usize(); - render_const_scalar(f, &b[offset..offset + size], memory_map, ty)?; + render_const_scalar_ns(f, &b[offset..offset + size], memory_map, ty)?; } f.write_str(")") } - TyKind::Adt(adt, subst) => { - let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else { + TyKind::Adt(def, args) => { + let def = match def.def_id() { + SolverDefId::AdtId(def) => def, + _ => unreachable!(), + }; + let Ok(layout) = f.db.layout_of_adt_ns(def, args, trait_env.clone()) else { return f.write_str(""); }; - match adt.0 { + match def { hir_def::AdtId::StructId(s) => { let data = f.db.struct_signature(s); write!(f, "{}", data.name.display(f.db, f.edition()))?; @@ -897,9 +956,9 @@ fn render_const_scalar( s.fields(f.db), f, &field_types, - f.db.trait_environment(adt.0.into()), + f.db.trait_environment(def.into()), &layout, - subst, + args, b, memory_map, ) @@ -929,9 +988,9 @@ fn render_const_scalar( var_id.fields(f.db), f, &field_types, - f.db.trait_environment(adt.0.into()), + f.db.trait_environment(def.into()), var_layout, - subst, + args, b, memory_map, ) @@ -939,16 +998,16 @@ fn render_const_scalar( } } TyKind::FnDef(..) => ty.hir_fmt(f), - TyKind::Function(_) | TyKind::Raw(_, _) => { + TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => { let it = u128::from_le_bytes(pad16(b, false)); write!(f, "{it:#X} as ")?; ty.hir_fmt(f) } TyKind::Array(ty, len) => { - let Some(len) = try_const_usize(f.db, len) else { + let Some(len) = consteval_nextsolver::try_const_usize(f.db, len) else { return f.write_str(""); }; - let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else { + let Ok(layout) = f.db.layout_of_ty_ns(ty, trait_env) else { return f.write_str(""); }; let size_one = layout.size.bytes_usize(); @@ -961,7 +1020,7 @@ fn render_const_scalar( f.write_str(", ")?; } let offset = size_one * i; - render_const_scalar(f, &b[offset..offset + size_one], memory_map, ty)?; + render_const_scalar_ns(f, &b[offset..offset + size_one], memory_map, ty)?; } f.write_str("]") } @@ -969,17 +1028,19 @@ fn render_const_scalar( TyKind::Closure(_, _) => f.write_str(""), TyKind::Coroutine(_, _) => f.write_str(""), TyKind::CoroutineWitness(_, _) => f.write_str(""), + TyKind::CoroutineClosure(_, _) => f.write_str(""), + TyKind::UnsafeBinder(_) => f.write_str(""), // The below arms are unreachable, since const eval will bail out before here. TyKind::Foreign(_) => f.write_str(""), - TyKind::Error + TyKind::Pat(_, _) => f.write_str(""), + TyKind::Error(..) | TyKind::Placeholder(_) - | TyKind::Alias(_) - | TyKind::AssociatedType(_, _) - | TyKind::OpaqueType(_, _) - | TyKind::BoundVar(_) - | TyKind::InferenceVar(_, _) => f.write_str(""), + | TyKind::Alias(_, _) + | TyKind::Param(_) + | TyKind::Bound(_, _) + | TyKind::Infer(_) => f.write_str(""), // The below arms are unreachable, since we handled them in ref case. - TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => f.write_str(""), + TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(_, _, _) => f.write_str(""), } } @@ -989,15 +1050,18 @@ fn render_variant_after_name( field_types: &ArenaMap>, trait_env: Arc, layout: &Layout, - subst: &Substitution, + args: GenericArgs<'_>, b: &[u8], memory_map: &MemoryMap, ) -> Result<(), HirDisplayError> { + let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block); match data.shape { FieldsShape::Record | FieldsShape::Tuple => { 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 ty = field_types[id] + .clone() + .substitute(Interner, &convert_args_for_result(interner, args.as_slice())); let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { return f.write_str(""); }; @@ -1045,18 +1109,30 @@ impl HirDisplay for Ty { &self, f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>, ) -> Result<(), HirDisplayError> { + let ty = self.to_nextsolver(DbInterner::new_with(db, None, None)); + ty.hir_fmt(f) + } +} + +impl<'db> HirDisplay for crate::next_solver::Ty<'db> { + fn hir_fmt( + &self, + f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>, + ) -> Result<(), HirDisplayError> { + let interner = DbInterner::new_with(db, None, None); if f.should_truncate() { return write!(f, "{TYPE_HINT_TRUNCATION}"); } - match self.kind(Interner) { + use rustc_type_ir::TyKind; + match self.kind() { TyKind::Never => write!(f, "!")?, TyKind::Str => write!(f, "str")?, - TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, - TyKind::Scalar(Scalar::Char) => write!(f, "char")?, - &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, - &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, - &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, + TyKind::Bool => write!(f, "bool")?, + TyKind::Char => write!(f, "char")?, + TyKind::Float(t) => write!(f, "{}", primitive::float_ty_to_string_ns(t))?, + TyKind::Int(t) => write!(f, "{}", primitive::int_ty_to_string_ns(t))?, + TyKind::Uint(t) => write!(f, "{}", primitive::uint_ty_to_string_ns(t))?, TyKind::Slice(t) => { write!(f, "[")?; t.hir_fmt(f)?; @@ -1066,27 +1142,27 @@ impl HirDisplay for Ty { write!(f, "[")?; t.hir_fmt(f)?; write!(f, "; ")?; - c.hir_fmt(f)?; + convert_const_for_result(interner, c).hir_fmt(f)?; write!(f, "]")?; } - kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => { - if let TyKind::Ref(_, l, _) = kind { + kind @ (TyKind::RawPtr(t, m) | TyKind::Ref(_, t, m)) => { + if let TyKind::Ref(l, _, _) = kind { f.write_char('&')?; - if f.render_lifetime(l) { - l.hir_fmt(f)?; + if f.render_region(l) { + convert_region_for_result(l).hir_fmt(f)?; f.write_char(' ')?; } match m { - Mutability::Not => (), - Mutability::Mut => f.write_str("mut ")?, + rustc_ast_ir::Mutability::Not => (), + rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?, } } else { write!( f, "*{}", match m { - Mutability::Not => "const ", - Mutability::Mut => "mut ", + rustc_ast_ir::Mutability::Not => "const ", + rustc_ast_ir::Mutability::Mut => "mut ", } )?; } @@ -1102,25 +1178,42 @@ impl HirDisplay for Ty { } }) }; - let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) { - TyKind::Dyn(dyn_ty) => { - let bounds = dyn_ty.bounds.skip_binders().interned(); - let render_lifetime = f.render_lifetime(&dyn_ty.lifetime); - (bounds.len() + render_lifetime as usize, contains_impl_fn(bounds)) + let contains_impl_fn_ns = |bounds: &[BoundExistentialPredicate<'_>]| { + bounds.iter().any(|bound| match bound.skip_binder() { + rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => { + let trait_ = match trait_ref.def_id { + SolverDefId::TraitId(id) => id, + _ => unreachable!(), + }; + fn_traits(db, trait_).any(|it| it == trait_) + } + _ => false, + }) + }; + let (preds_to_print, has_impl_fn_pred) = match t.kind() { + TyKind::Dynamic(bounds, region, _) => { + let render_lifetime = f.render_region(region); + ( + bounds.len() + render_lifetime as usize, + contains_impl_fn_ns(bounds.as_slice()), + ) } - TyKind::Alias(AliasTy::Opaque(OpaqueTy { - opaque_ty_id, - substitution: parameters, - })) - | TyKind::OpaqueType(opaque_ty_id, parameters) => { - let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into()); + TyKind::Alias(AliasTyKind::Opaque, ty) => { + let opaque_ty_id = match ty.def_id { + SolverDefId::InternedOpaqueTyId(id) => id, + _ => unreachable!(), + }; + let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id); if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { let datas = db .return_type_impl_traits(func) .expect("impl trait id without data"); let data = (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - let bounds = data.substitute(Interner, parameters); + let bounds = data.substitute( + Interner, + &convert_args_for_result(interner, ty.args.as_slice()), + ); let mut len = bounds.skip_binders().len(); // Don't count Sized but count when it absent @@ -1167,24 +1260,31 @@ impl HirDisplay for Ty { t.hir_fmt(f)?; } } - TyKind::Tuple(_, substs) => { - if substs.len(Interner) == 1 { + TyKind::Tuple(tys) => { + if tys.len() == 1 { write!(f, "(")?; - substs.at(Interner, 0).hir_fmt(f)?; + tys.as_slice()[0].hir_fmt(f)?; write!(f, ",)")?; } else { write!(f, "(")?; - f.write_joined(substs.as_slice(Interner), ", ")?; + f.write_joined(tys.as_slice(), ", ")?; write!(f, ")")?; } } - TyKind::Function(fn_ptr) => { - let sig = CallableSig::from_fn_ptr(fn_ptr); + TyKind::FnPtr(sig, header) => { + let sig = CallableSig::from_fn_sig_and_header(interner, sig, header); sig.hir_fmt(f)?; } - TyKind::FnDef(def, parameters) => { - let def = from_chalk(db, *def); - let sig = db.callable_item_signature(def).substitute(Interner, parameters); + TyKind::FnDef(def, args) => { + let def = match def { + SolverDefId::FunctionId(id) => CallableDefId::FunctionId(id), + SolverDefId::Ctor(Ctor::Enum(e)) => CallableDefId::EnumVariantId(e), + SolverDefId::Ctor(Ctor::Struct(s)) => CallableDefId::StructId(s), + _ => unreachable!(), + }; + let sig = db + .callable_item_signature(def) + .substitute(Interner, &convert_args_for_result(interner, args.as_slice())); if f.display_kind.is_source_code() { // `FnDef` is anonymous and there's no surface syntax for it. Show it as a @@ -1222,6 +1322,7 @@ impl HirDisplay for Ty { }; f.end_location_link(); + let parameters = convert_args_for_result(interner, args.as_slice()); if parameters.len(Interner) > 0 { let generic_def_id = GenericDefId::from_callable(db, def); let generics = generics(db, generic_def_id); @@ -1280,11 +1381,15 @@ impl HirDisplay for Ty { ret.hir_fmt(f)?; } } - TyKind::Adt(AdtId(def_id), parameters) => { - f.start_location_link((*def_id).into()); + TyKind::Adt(def, parameters) => { + let def_id = match def.def_id() { + SolverDefId::AdtId(id) => id, + _ => unreachable!(), + }; + f.start_location_link(def_id.into()); match f.display_kind { DisplayKind::Diagnostics | DisplayKind::Test => { - let name = match *def_id { + let name = match def_id { hir_def::AdtId::StructId(it) => db.struct_signature(it).name.clone(), hir_def::AdtId::UnionId(it) => db.union_signature(it).name.clone(), hir_def::AdtId::EnumId(it) => db.enum_signature(it).name.clone(), @@ -1294,7 +1399,7 @@ impl HirDisplay for Ty { DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => { if let Some(path) = find_path::find_path( db, - ItemInNs::Types((*def_id).into()), + ItemInNs::Types(def_id.into()), module_id, PrefixKind::Plain, false, @@ -1316,55 +1421,49 @@ impl HirDisplay for Ty { } f.end_location_link(); - let generic_def = self.as_generic_def(db); - - hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?; + hir_fmt_generics( + f, + convert_args_for_result(interner, parameters.as_slice()).as_slice(Interner), + def.def_id().try_into().ok(), + None, + )?; } - TyKind::AssociatedType(assoc_type_id, parameters) => { - let type_alias = from_assoc_type_id(*assoc_type_id); - let trait_ = match type_alias.lookup(db).container { - ItemContainerId::TraitId(it) => it, - _ => panic!("not an associated type"), + TyKind::Alias(AliasTyKind::Projection, alias_ty) => { + let type_alias = match alias_ty.def_id { + SolverDefId::TypeAliasId(id) => id, + _ => unreachable!(), }; - let trait_data = db.trait_signature(trait_); - let type_alias_data = db.type_alias_signature(type_alias); + let parameters = convert_args_for_result(interner, alias_ty.args.as_slice()); - // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) - if f.display_kind.is_test() { - f.start_location_link(trait_.into()); - write!(f, "{}", trait_data.name.display(f.db, f.edition()))?; - f.end_location_link(); - write!(f, "::")?; + let projection_ty = ProjectionTy { + associated_ty_id: to_assoc_type_id(type_alias), + substitution: parameters.clone(), + }; - f.start_location_link(type_alias.into()); - write!(f, "{}", type_alias_data.name.display(f.db, f.edition()))?; - f.end_location_link(); - // Note that the generic args for the associated type come before those for the - // trait (including the self type). - hir_fmt_generics(f, parameters.as_slice(Interner), None, None) - } else { - let projection_ty = ProjectionTy { - associated_ty_id: to_assoc_type_id(type_alias), - substitution: parameters.clone(), - }; - - projection_ty.hir_fmt(f) - }?; + projection_ty.hir_fmt(f)?; } TyKind::Foreign(type_alias) => { - let alias = from_foreign_def_id(*type_alias); + let alias = match type_alias { + SolverDefId::ForeignId(id) => id, + _ => unreachable!(), + }; let type_alias = db.type_alias_signature(alias); f.start_location_link(alias.into()); write!(f, "{}", type_alias.name.display(f.db, f.edition()))?; f.end_location_link(); } - TyKind::OpaqueType(opaque_ty_id, parameters) => { + TyKind::Alias(AliasTyKind::Opaque, alias_ty) => { + let opaque_ty_id = match alias_ty.def_id { + SolverDefId::InternedOpaqueTyId(id) => id, + _ => unreachable!(), + }; + let parameters = convert_args_for_result(interner, alias_ty.args.as_slice()); if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); } - let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into()); + let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id); match impl_trait_id { ImplTraitId::ReturnTypeImplTrait(func, idx) => { let datas = @@ -1376,7 +1475,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", - Either::Left(self), + Either::Left(&convert_ty_for_result(interner, *self)), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1391,7 +1490,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", - Either::Left(self), + Either::Left(&convert_ty_for_result(interner, *self)), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1426,6 +1525,11 @@ impl HirDisplay for Ty { } } TyKind::Closure(id, substs) => { + let id = match id { + SolverDefId::InternedClosureId(id) => id, + _ => unreachable!(), + }; + let substs = convert_args_for_result(interner, substs.as_slice()); if f.display_kind.is_source_code() { if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( @@ -1435,22 +1539,23 @@ impl HirDisplay for Ty { never!("Only `impl Fn` is valid for displaying closures in source code"); } } + let chalk_id: chalk_ir::ClosureId<_> = id.into(); match f.closure_style { ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"), ClosureStyle::ClosureWithId => { - return write!(f, "{{closure#{:?}}}", id.0.index()); + return write!(f, "{{closure#{:?}}}", chalk_id.0.index()); } ClosureStyle::ClosureWithSubst => { - write!(f, "{{closure#{:?}}}", id.0.index())?; + write!(f, "{{closure#{:?}}}", chalk_id.0.index())?; return hir_fmt_generics(f, substs.as_slice(Interner), None, None); } _ => (), } - let sig = ClosureSubst(substs).sig_ty().callable_sig(db); + let sig = ClosureSubst(&substs).sig_ty().callable_sig(db); if let Some(sig) = sig { - let InternedClosure(def, _) = db.lookup_intern_closure((*id).into()); + let InternedClosure(def, _) = db.lookup_intern_closure(id); let infer = db.infer(def); - let (_, kind) = infer.closure_info(id); + let (_, kind) = infer.closure_info(&chalk_id); match f.closure_style { ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?, ClosureStyle::RANotation => write!(f, "|")?, @@ -1478,7 +1583,11 @@ impl HirDisplay for Ty { } } TyKind::Placeholder(idx) => { - let id = from_placeholder_idx(db, *idx); + let placeholder_index = chalk_ir::PlaceholderIndex { + idx: idx.bound.var.as_usize(), + ui: chalk_ir::UniverseIndex { counter: idx.universe.as_usize() }, + }; + let id = from_placeholder_idx(db, placeholder_index); let generics = generics(db, id.parent); let param_data = &generics[id.local_id]; match param_data { @@ -1501,14 +1610,20 @@ impl HirDisplay for Ty { .map(|pred| pred.clone().substitute(Interner, &substs)) .filter(|wc| match wc.skip_binders() { WhereClause::Implemented(tr) => { - tr.self_type_parameter(Interner) == *self + tr.self_type_parameter(Interner) + == convert_ty_for_result(interner, *self) } WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _, - }) => proj.self_type_parameter(db) == *self, + }) => { + proj.self_type_parameter(db) + == convert_ty_for_result(interner, *self) + } WhereClause::AliasEq(_) => false, - WhereClause::TypeOutlives(to) => to.ty == *self, + WhereClause::TypeOutlives(to) => { + to.ty == convert_ty_for_result(interner, *self) + } WhereClause::LifetimeOutlives(_) => false, }) .collect::>(); @@ -1516,7 +1631,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", - Either::Left(self), + Either::Left(&convert_ty_for_result(interner, *self)), &bounds, SizedByDefault::Sized { anchor: krate }, )?; @@ -1527,8 +1642,17 @@ impl HirDisplay for Ty { } } } - TyKind::BoundVar(idx) => idx.hir_fmt(f)?, - TyKind::Dyn(dyn_ty) => { + TyKind::Param(_) => write!(f, "{{param}}")?, + TyKind::Bound(debruijn_index, ty) => { + let idx = chalk_ir::BoundVar { + debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), + index: ty.var.as_usize(), + }; + idx.hir_fmt(f)? + } + TyKind::Dynamic(..) => { + let ty = convert_ty_for_result(interner, *self); + let chalk_ir::TyKind::Dyn(dyn_ty) = ty.kind(Interner) else { unreachable!() }; // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation. // FIXME: `Iterator::partition_in_place()` or `Vec::extract_if()` may make it // more efficient when either of them hits stable. @@ -1544,7 +1668,7 @@ impl HirDisplay for Ty { bounds.push(Binders::empty( Interner, chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { - ty: self.clone(), + ty: ty.clone(), lifetime: dyn_ty.lifetime.clone(), }), )); @@ -1553,69 +1677,26 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "dyn", - Either::Left(self), + Either::Left(&ty), &bounds, SizedByDefault::NotSized, )?; } - TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, - TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { - if !f.display_kind.allows_opaque() { - return Err(HirDisplayError::DisplaySourceCodeError( - DisplaySourceCodeError::OpaqueType, - )); - } - let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()); - match impl_trait_id { - ImplTraitId::ReturnTypeImplTrait(func, idx) => { - let datas = - db.return_type_impl_traits(func).expect("impl trait id without data"); - let data = - (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - let bounds = data.substitute(Interner, &opaque_ty.substitution); - let krate = func.krate(db); - write_bounds_like_dyn_trait_with_prefix( - f, - "impl", - Either::Left(self), - bounds.skip_binders(), - SizedByDefault::Sized { anchor: krate }, - )?; - } - ImplTraitId::TypeAliasImplTrait(alias, idx) => { - let datas = - db.type_alias_impl_traits(alias).expect("impl trait id without data"); - let data = - (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - let bounds = data.substitute(Interner, &opaque_ty.substitution); - let krate = alias.krate(db); - write_bounds_like_dyn_trait_with_prefix( - f, - "impl", - Either::Left(self), - bounds.skip_binders(), - SizedByDefault::Sized { anchor: krate }, - )?; - } - ImplTraitId::AsyncBlockTypeImplTrait(..) => { - write!(f, "{{async block}}")?; - } - }; - } - TyKind::Error => { + TyKind::Error(_) => { if f.display_kind.is_source_code() { f.write_char('_')?; } else { write!(f, "{{unknown}}")?; } } - TyKind::InferenceVar(..) => write!(f, "_")?, + TyKind::Infer(..) => write!(f, "_")?, TyKind::Coroutine(_, subst) => { if f.display_kind.is_source_code() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::Coroutine, )); } + let subst = convert_args_for_result(interner, subst.as_slice()); let subst = subst.as_slice(Interner); let a: Option> = subst .get(subst.len() - 3..) @@ -1637,6 +1718,10 @@ impl HirDisplay for Ty { } } TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?, + TyKind::Pat(_, _) => write!(f, "{{pat}}")?, + TyKind::UnsafeBinder(_) => write!(f, "{{unsafe binder}}")?, + TyKind::CoroutineClosure(_, _) => write!(f, "{{coroutine closure}}")?, + TyKind::Alias(_, _) => write!(f, "{{alias}}")?, } Ok(()) } diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index 237cc34d70..8bd555f5c0 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -615,7 +615,6 @@ fn receiver_for_self_ty<'db>( }, ); - crate::next_solver::EarlyBinder::bind(receiver_ty).instantiate(interner, args) } diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 2d0471d7e5..fb7b5e1c83 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -153,7 +153,7 @@ fn layout_of_simd_ty<'db>( return Err(LayoutError::InvalidSimdType); }; - let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64; + let e_len = try_const_usize(db, e_len).ok_or(LayoutError::HasErrorConst)? as u64; let e_ly = db.layout_of_ty_ns(e_ty, env)?; let cx = LayoutCx::new(dl); @@ -272,7 +272,7 @@ pub fn layout_of_ty_ns_query<'db>( cx.calc.univariant(&fields, &ReprOptions::default(), kind)? } TyKind::Array(element, count) => { - let count = try_const_usize(db, &count).ok_or(LayoutError::HasErrorConst)? as u64; + let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64; let element = db.layout_of_ty_ns(element, trait_env)?; cx.calc.array_like::<_, _, ()>(&element, Some(count))? } diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 2b0dc931ea..81894830b5 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -90,6 +90,7 @@ use intern::{Symbol, sym}; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; +use rustc_type_ir::inherent::SliceLike; use syntax::ast::{ConstArg, make}; use traits::FnTrait; use triomphe::Arc; @@ -100,6 +101,7 @@ use crate::{ display::{DisplayTarget, HirDisplay}, generics::Generics, infer::unify::InferenceTable, + next_solver::{DbInterner, mapping::convert_ty_for_result}, }; pub use autoderef::autoderef; @@ -560,6 +562,27 @@ impl CallableSig { abi: fn_ptr.sig.abi, } } + pub fn from_fn_sig_and_header<'db>( + interner: DbInterner<'db>, + sig: crate::next_solver::Binder<'db, rustc_type_ir::FnSigTys>>, + header: rustc_type_ir::FnHeader>, + ) -> CallableSig { + CallableSig { + // FIXME: what to do about lifetime params? -> return PolyFnSig + params_and_return: Arc::from_iter( + sig.skip_binder() + .inputs_and_output + .iter() + .map(|t| convert_ty_for_result(interner, t)), + ), + is_varargs: header.c_variadic, + safety: match header.safety { + next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe, + next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe, + }, + abi: header.abi, + } + } pub fn to_fn_ptr(&self) -> FnPointer { FnPointer { diff --git a/crates/hir-ty/src/next_solver/mapping.rs b/crates/hir-ty/src/next_solver/mapping.rs index 20cd8626f2..b50fccb832 100644 --- a/crates/hir-ty/src/next_solver/mapping.rs +++ b/crates/hir-ty/src/next_solver/mapping.rs @@ -1290,7 +1290,10 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) .intern(Interner) } -fn convert_const_for_result<'db>(interner: DbInterner<'db>, const_: Const<'db>) -> crate::Const { +pub fn convert_const_for_result<'db>( + interner: DbInterner<'db>, + const_: Const<'db>, +) -> crate::Const { let value: chalk_ir::ConstValue = match const_.kind() { rustc_type_ir::ConstKind::Param(_) => unimplemented!(), rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => { @@ -1343,7 +1346,7 @@ fn convert_const_for_result<'db>(interner: DbInterner<'db>, const_: Const<'db>) chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner) } -fn convert_region_for_result<'db>(region: Region<'db>) -> crate::Lifetime { +pub fn convert_region_for_result<'db>(region: Region<'db>) -> crate::Lifetime { match region.kind() { rustc_type_ir::RegionKind::ReEarlyParam(early) => unimplemented!(), rustc_type_ir::RegionKind::ReBound(db, bound) => chalk_ir::Lifetime::new( diff --git a/crates/hir-ty/src/next_solver/project/solve_normalize.rs b/crates/hir-ty/src/next_solver/project/solve_normalize.rs index a8fb2ae14f..42c238febf 100644 --- a/crates/hir-ty/src/next_solver/project/solve_normalize.rs +++ b/crates/hir-ty/src/next_solver/project/solve_normalize.rs @@ -11,16 +11,25 @@ use rustc_type_ir::{ use crate::next_solver::{ Binder, Const, ConstKind, DbInterner, Goal, ParamEnv, Predicate, PredicateKind, Span, Term, Ty, - TyKind, + TyKind, TypingMode, fulfill::{FulfillmentCtxt, NextSolverError}, infer::{ - InferCtxt, + DbInternerInferExt, InferCtxt, at::At, traits::{Obligation, ObligationCause}, }, util::PlaceholderReplacer, }; +pub fn normalize<'db, T>(interner: DbInterner<'db>, param_env: ParamEnv<'db>, value: T) -> T +where + T: TypeFoldable>, +{ + let infer_ctxt = interner.infer_ctxt().build(TypingMode::non_body_analysis()); + let cause = ObligationCause::dummy(); + deeply_normalize(infer_ctxt.at(&cause, param_env), value.clone()).unwrap_or(value) +} + /// Deeply normalize all aliases in `value`. This does not handle inference and expects /// its input to be already fully resolved. pub fn deeply_normalize<'db, T>(at: At<'_, 'db>, value: T) -> Result>> diff --git a/crates/hir-ty/src/primitive.rs b/crates/hir-ty/src/primitive.rs index a4e077ba63..d2901f7fc5 100644 --- a/crates/hir-ty/src/primitive.rs +++ b/crates/hir-ty/src/primitive.rs @@ -34,6 +34,40 @@ pub fn float_ty_to_string(ty: FloatTy) -> &'static str { } } +pub fn int_ty_to_string_ns(ty: rustc_type_ir::IntTy) -> &'static str { + use rustc_type_ir::IntTy; + match ty { + IntTy::Isize => "isize", + IntTy::I8 => "i8", + IntTy::I16 => "i16", + IntTy::I32 => "i32", + IntTy::I64 => "i64", + IntTy::I128 => "i128", + } +} + +pub fn uint_ty_to_string_ns(ty: rustc_type_ir::UintTy) -> &'static str { + use rustc_type_ir::UintTy; + match ty { + UintTy::Usize => "usize", + UintTy::U8 => "u8", + UintTy::U16 => "u16", + UintTy::U32 => "u32", + UintTy::U64 => "u64", + UintTy::U128 => "u128", + } +} + +pub fn float_ty_to_string_ns(ty: rustc_type_ir::FloatTy) -> &'static str { + use rustc_type_ir::FloatTy; + match ty { + FloatTy::F16 => "f16", + FloatTy::F32 => "f32", + FloatTy::F64 => "f64", + FloatTy::F128 => "f128", + } +} + pub(super) fn int_ty_from_builtin(t: BuiltinInt) -> IntTy { match t { BuiltinInt::Isize => IntTy::Isize, diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index d98b6602ef..1c3da438cb 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -157,11 +157,13 @@ fn check_impl( }; let range = node.as_ref().original_file_range_rooted(&db); if let Some(expected) = types.remove(&range) { - let actual = if display_source { - ty.display_source_code(&db, def.module(&db), true).unwrap() - } else { - ty.display_test(&db, display_target).to_string() - }; + let actual = salsa::attach(&db, || { + if display_source { + ty.display_source_code(&db, def.module(&db), true).unwrap() + } else { + ty.display_test(&db, display_target).to_string() + } + }); assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); } } @@ -173,11 +175,13 @@ fn check_impl( }; let range = node.as_ref().original_file_range_rooted(&db); if let Some(expected) = types.remove(&range) { - let actual = if display_source { - ty.display_source_code(&db, def.module(&db), true).unwrap() - } else { - ty.display_test(&db, display_target).to_string() - }; + let actual = salsa::attach(&db, || { + if display_source { + ty.display_source_code(&db, def.module(&db), true).unwrap() + } else { + ty.display_test(&db, display_target).to_string() + } + }); assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); } if let Some(expected) = adjustments.remove(&range) { @@ -203,11 +207,13 @@ fn check_impl( continue; }; let range = node.as_ref().original_file_range_rooted(&db); - let actual = format!( - "expected {}, got {}", - mismatch.expected.display_test(&db, display_target), - mismatch.actual.display_test(&db, display_target) - ); + let actual = salsa::attach(&db, || { + format!( + "expected {}, got {}", + mismatch.expected.display_test(&db, display_target), + mismatch.actual.display_test(&db, display_target) + ) + }); match mismatches.remove(&range) { Some(annotation) => assert_eq!(actual, annotation), None => format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual), @@ -402,7 +408,9 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { for (def, krate) in defs { let (body, source_map) = db.body_with_source_map(def); let infer = db.infer(def); - infer_def(infer, body, source_map, krate); + salsa::attach(&db, || { + infer_def(infer, body, source_map, krate); + }) } buf.truncate(buf.trim_end().len()); diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs index 5893894c33..b001ac1e82 100644 --- a/crates/hir-ty/src/tests/closure_captures.rs +++ b/crates/hir-ty/src/tests/closure_captures.rs @@ -67,11 +67,13 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec .join(", "), }; let place = capture.display_place(closure.0, db); - let capture_ty = capture - .ty - .skip_binders() - .display_test(db, DisplayTarget::from_crate(db, module.krate())) - .to_string(); + let capture_ty = salsa::attach(db, || { + capture + .ty + .skip_binders() + .display_test(db, DisplayTarget::from_crate(db, module.krate())) + .to_string() + }); let spans = capture .spans() .iter() diff --git a/crates/hir-ty/src/tests/opaque_types.rs b/crates/hir-ty/src/tests/opaque_types.rs index 36578545a9..11d1a58e53 100644 --- a/crates/hir-ty/src/tests/opaque_types.rs +++ b/crates/hir-ty/src/tests/opaque_types.rs @@ -71,7 +71,7 @@ fn test() { let x = S3.baz(); //^ Binary> let y = x.1.0.bar(); - //^ Unary> + //^ Unary<::Item> } "#, ); diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 212fec4a4e..fd8c641d86 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -2299,10 +2299,10 @@ trait Foo { } "#, expect![[r#" - 83..86 'bar': Foo::Bar + 83..86 'bar': ::Bar 105..133 '{ ... }': () - 119..120 '_': Foo::Bar - 123..126 'bar': Foo::Bar + 119..120 '_': ::Bar + 123..126 'bar': ::Bar "#]], ); } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 9d72105624..a311e57974 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -408,11 +408,11 @@ fn test() { let x: ::Item = 1; // ^ u32 let y: ::Item = u; - // ^ Iterable::Item + // ^ ::Item let z: T::Item = u; - // ^ Iterable::Item + // ^ ::Item let a: ::Item = u; - // ^ Iterable::Item + // ^ ::Item }"#, ); } @@ -454,7 +454,7 @@ impl S { fn test() { let s: S; s.foo(); - // ^^^^^^^ Iterable::Item + // ^^^^^^^ ::Item }"#, ); } @@ -470,7 +470,7 @@ trait Foo { type A; fn test(a: Self::A, _: impl Bar) { a; - //^ Foo::A + //^ ::A } }"#, ); @@ -969,7 +969,7 @@ impl ApplyL for RefMutL { fn test() { let y: as ApplyL>::Out = no_matter; y; -} //^ ApplyL::Out +} //^ ::Out "#, ); } @@ -986,7 +986,7 @@ fn foo(t: T) -> ::Out; fn test(t: T) { let y = foo(t); y; -} //^ ApplyL::Out +} //^ ::Out "#, ); } @@ -1695,7 +1695,7 @@ fn test>(x: T, y: impl Trait) { }"#, expect![[r#" 49..50 't': T - 77..79 '{}': Trait::Type + 77..79 '{}': ::Type 111..112 't': T 122..124 '{}': U 154..155 't': T @@ -2293,7 +2293,7 @@ impl Trait for S2 { }"#, expect![[r#" 40..44 'self': &'? Self - 46..47 'x': Trait::Item + 46..47 'x': ::Item 126..130 'self': &'? S 132..133 'x': u32 147..161 '{ let y = x; }': () @@ -2410,7 +2410,7 @@ trait Trait2 {} fn test() where T: Trait2 { let x: T::Item = no_matter; -} //^^^^^^^^^ Trait::Item +} //^^^^^^^^^ ::Item "#, ); } @@ -2445,7 +2445,7 @@ trait Trait { fn test() where T: Trait { let x: T::Item = no_matter; -} //^^^^^^^^^ Trait::Item +} //^^^^^^^^^ ::Item "#, ); } @@ -2475,7 +2475,7 @@ fn test(t: T) where T: UnificationStoreMut { t.push(x); let y: Key; (x, y); -} //^^^^^^ (UnificationStoreBase::Key, UnificationStoreBase::Key) +} //^^^^^^ (::Key, ::Key) "#, ); } @@ -3488,7 +3488,7 @@ fn foo() { let x = ::boo(); }"#, expect![[r#" - 132..163 '{ ... }': Bar::Output + 132..163 '{ ... }': ::Output 146..153 'loop {}': ! 151..153 '{}': () 306..358 '{ ...o(); }': () @@ -4213,7 +4213,7 @@ fn g<'a, T: 'a>(v: impl Trait = &'a T>) { let a = v.get::(); //^ &'a T let a = v.get::<()>(); - //^ Trait::Assoc = &'a T>, ()> + //^ = &'a T> as Trait>::Assoc<()> } fn h<'a>(v: impl Trait = &'a i32> + Trait = &'a i64>) { let a = v.get::(); @@ -4280,7 +4280,7 @@ where let a = t.get::(); //^ usize let a = t.get::<()>(); - //^ Trait::Assoc + //^ ::Assoc<()> } "#, @@ -4857,29 +4857,29 @@ async fn baz i32>(c: T) { 37..38 'a': T 43..83 '{ ...ait; }': () 43..83 '{ ...ait; }': impl Future - 53..57 'fut1': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 53..57 'fut1': >::CallRefFuture<'?> 60..61 'a': T - 60..64 'a(0)': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 60..64 'a(0)': >::CallRefFuture<'?> 62..63 '0': u32 - 70..74 'fut1': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 70..74 'fut1': >::CallRefFuture<'?> 70..80 'fut1.await': i32 124..129 'mut b': T 134..174 '{ ...ait; }': () 134..174 '{ ...ait; }': impl Future - 144..148 'fut2': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 144..148 'fut2': >::CallRefFuture<'?> 151..152 'b': T - 151..155 'b(0)': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 151..155 'b(0)': >::CallRefFuture<'?> 153..154 '0': u32 - 161..165 'fut2': AsyncFnMut::CallRefFuture<'?, T, (u32,)> + 161..165 'fut2': >::CallRefFuture<'?> 161..171 'fut2.await': i32 216..217 'c': T 222..262 '{ ...ait; }': () 222..262 '{ ...ait; }': impl Future - 232..236 'fut3': AsyncFnOnce::CallOnceFuture + 232..236 'fut3': >::CallOnceFuture 239..240 'c': T - 239..243 'c(0)': AsyncFnOnce::CallOnceFuture + 239..243 'c(0)': >::CallOnceFuture 241..242 '0': u32 - 249..253 'fut3': AsyncFnOnce::CallOnceFuture + 249..253 'fut3': >::CallOnceFuture 249..259 'fut3.await': i32 "#]], ); @@ -4947,7 +4947,7 @@ where "#, expect![[r#" 84..86 'de': D - 135..138 '{ }': Deserializer::Error<'de, D> + 135..138 '{ }': >::Error "#]], ); } @@ -5020,7 +5020,7 @@ fn main() { 294..298 'iter': Box + 'static> 294..310 'iter.i...iter()': Box + 'static> 152..156 'self': &'? mut Box - 177..208 '{ ... }': Option> + 177..208 '{ ... }': Option<::Item> 191..198 'loop {}': ! 196..198 '{}': () "#]], diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 11486ec8d6..4dde019b50 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -85,7 +85,9 @@ use hir_ty::{ layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution, mir::{MutBorrowKind, interpret_mir}, - next_solver::{DbInterner, GenericArgs, SolverDefId, infer::InferCtxt}, + next_solver::{ + DbInterner, GenericArgs, SolverDefId, infer::InferCtxt, mapping::ChalkToNextSolver, + }, primitive::UintTy, traits::FnTrait, }; @@ -1814,12 +1816,15 @@ impl Adt { } pub fn layout(self, db: &dyn HirDatabase) -> Result { - db.layout_of_adt( + let env = db.trait_environment(self.into()); + let interner = DbInterner::new_with(db, Some(env.krate), env.block); + db.layout_of_adt_ns( self.into(), TyBuilder::adt(db, self.into()) .fill_with_defaults(db, || TyKind::Error.intern(Interner)) - .build_into_subst(), - db.trait_environment(self.into()), + .build_into_subst() + .to_nextsolver(interner), + env, ) .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) } diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index 7a8c70f190..f03f61d10e 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -1,3 +1,4 @@ +use base_db::salsa; use expect_test::{Expect, expect}; use hir::HirDisplay; @@ -13,7 +14,11 @@ fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, let ty = completion_context .expected_type - .map(|t| t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string()) + .map(|t| { + salsa::attach(&db, || { + t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string() + }) + }) .unwrap_or("?".to_owned()); let name = diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index e4c7d42ffe..1f9d10c92b 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -912,7 +912,7 @@ pub(super) fn literal( }; let ty = ty.display(sema.db, display_target); - let mut s = format!("```rust\n{ty}\n```\n___\n\n"); + let mut s = salsa::attach(sema.db, || format!("```rust\n{ty}\n```\n___\n\n")); match value { Ok(value) => { let backtick_len = value.chars().filter(|c| *c == '`').count(); diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 424890fe37..d7d3171664 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -738,44 +738,46 @@ fn label_of_ty( config: &InlayHintsConfig, display_target: DisplayTarget, ) -> Result<(), HirDisplayError> { - let iter_item_type = hint_iterator(sema, famous_defs, ty); - match iter_item_type { - Some((iter_trait, item, ty)) => { - const LABEL_START: &str = "impl "; - const LABEL_ITERATOR: &str = "Iterator"; - const LABEL_MIDDLE: &str = "<"; - const LABEL_ITEM: &str = "Item"; - const LABEL_MIDDLE2: &str = " = "; - const LABEL_END: &str = ">"; + salsa::attach(sema.db, || { + let iter_item_type = hint_iterator(sema, famous_defs, ty); + match iter_item_type { + Some((iter_trait, item, ty)) => { + const LABEL_START: &str = "impl "; + const LABEL_ITERATOR: &str = "Iterator"; + const LABEL_MIDDLE: &str = "<"; + const LABEL_ITEM: &str = "Item"; + const LABEL_MIDDLE2: &str = " = "; + const LABEL_END: &str = ">"; - max_length = max_length.map(|len| { - len.saturating_sub( - LABEL_START.len() - + LABEL_ITERATOR.len() - + LABEL_MIDDLE.len() - + LABEL_MIDDLE2.len() - + LABEL_END.len(), - ) - }); + max_length = max_length.map(|len| { + len.saturating_sub( + LABEL_START.len() + + LABEL_ITERATOR.len() + + LABEL_MIDDLE.len() + + LABEL_MIDDLE2.len() + + LABEL_END.len(), + ) + }); - label_builder.write_str(LABEL_START)?; - label_builder.start_location_link(ModuleDef::from(iter_trait).into()); - label_builder.write_str(LABEL_ITERATOR)?; - label_builder.end_location_link(); - label_builder.write_str(LABEL_MIDDLE)?; - label_builder.start_location_link(ModuleDef::from(item).into()); - label_builder.write_str(LABEL_ITEM)?; - label_builder.end_location_link(); - label_builder.write_str(LABEL_MIDDLE2)?; - rec(sema, famous_defs, max_length, &ty, label_builder, config, display_target)?; - label_builder.write_str(LABEL_END)?; - Ok(()) + label_builder.write_str(LABEL_START)?; + label_builder.start_location_link(ModuleDef::from(iter_trait).into()); + label_builder.write_str(LABEL_ITERATOR)?; + label_builder.end_location_link(); + label_builder.write_str(LABEL_MIDDLE)?; + label_builder.start_location_link(ModuleDef::from(item).into()); + label_builder.write_str(LABEL_ITEM)?; + label_builder.end_location_link(); + label_builder.write_str(LABEL_MIDDLE2)?; + rec(sema, famous_defs, max_length, &ty, label_builder, config, display_target)?; + label_builder.write_str(LABEL_END)?; + Ok(()) + } + None => ty + .display_truncated(sema.db, max_length, display_target) + .with_closure_style(config.closure_style) + .write_to(label_builder), } - None => ty - .display_truncated(sema.db, max_length, display_target) - .with_closure_style(config.closure_style) - .write_to(label_builder), - } + }) } let mut label_builder = InlayHintLabelBuilder { diff --git a/crates/ide/src/inlay_hints/adjustment.rs b/crates/ide/src/inlay_hints/adjustment.rs index 39554d7777..e39a5f8889 100644 --- a/crates/ide/src/inlay_hints/adjustment.rs +++ b/crates/ide/src/inlay_hints/adjustment.rs @@ -10,7 +10,7 @@ use hir::{ Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref, PointerCast, Safety, }; -use ide_db::famous_defs::FamousDefs; +use ide_db::{base_db::salsa, famous_defs::FamousDefs}; use ide_db::text_edit::TextEditBuilder; use syntax::ast::{self, AstNode, prec::ExprPrecedence}; @@ -201,13 +201,15 @@ pub(super) fn hints( text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() }, linked_location: None, tooltip: Some(config.lazy_tooltip(|| { - InlayTooltip::Markdown(format!( - "`{}` → `{}`\n\n**{}**\n\n{}", - source.display(sema.db, display_target), - target.display(sema.db, display_target), - coercion, - detailed_tooltip - )) + salsa::attach(sema.db, || { + InlayTooltip::Markdown(format!( + "`{}` → `{}`\n\n**{}**\n\n{}", + source.display(sema.db, display_target), + target.display(sema.db, display_target), + coercion, + detailed_tooltip + )) + }) })), }; if postfix { &mut post } else { &mut pre }.label.append_part(label); diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 5349ebb7c8..1c66473bf9 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -67,7 +67,7 @@ use ide_db::{ FxHashMap, FxIndexSet, LineIndexDatabase, base_db::{ CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath, - salsa::Cancelled, + salsa::{self, Cancelled}, }, prime_caches, symbol_index, }; @@ -461,7 +461,9 @@ impl Analysis { hasher: impl Fn(&InlayHint) -> u64 + Send + UnwindSafe, ) -> Cancellable> { self.with_db(|db| { - inlay_hints::inlay_hints_resolve(db, file_id, resolve_range, hash, config, hasher) + salsa::attach(db, || { + inlay_hints::inlay_hints_resolve(db, file_id, resolve_range, hash, config, hasher) + }) }) } @@ -536,7 +538,7 @@ impl Analysis { config: &HoverConfig, range: FileRange, ) -> Cancellable>> { - self.with_db(|db| hover::hover(db, range, config)) + self.with_db(|db| salsa::attach(db, || hover::hover(db, range, config))) } /// Returns moniker of symbol at position. @@ -544,7 +546,7 @@ impl Analysis { &self, position: FilePosition, ) -> Cancellable>>> { - self.with_db(|db| moniker::moniker(db, position)) + self.with_db(|db| salsa::attach(db, || moniker::moniker(db, position))) } /// Returns URL(s) for the documentation of the symbol under the cursor. @@ -640,7 +642,7 @@ impl Analysis { /// Returns the set of possible targets to run for the current file. pub fn runnables(&self, file_id: FileId) -> Cancellable> { - self.with_db(|db| runnables::runnables(db, file_id)) + self.with_db(|db| salsa::attach(db, || runnables::runnables(db, file_id))) } /// Returns the set of tests for the given file position. diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 61b4de0e0e..1b6a4b726e 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -10,6 +10,7 @@ use hir::{ }; use ide_db::{ FileId, FileRange, RootDatabase, SymbolKind, + base_db::salsa, defs::Definition, documentation::{Documentation, HasDocs}, }; @@ -377,8 +378,9 @@ where ) .map(|mut res| { res.docs = self.docs(db); - res.description = - Some(self.display(db, self.krate(db).to_display_target(db)).to_string()); + res.description = salsa::attach(db, || { + Some(self.display(db, self.krate(db).to_display_target(db)).to_string()) + }); res.container_name = self.container_name(db); res }), @@ -485,8 +487,9 @@ impl TryToNav for hir::Field { NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map( |mut res| { res.docs = self.docs(db); - res.description = - Some(self.display(db, krate.to_display_target(db)).to_string()); + res.description = salsa::attach(db, || { + Some(self.display(db, krate.to_display_target(db)).to_string()) + }); res }, ) diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 77c84292cf..6d33ddcde0 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -10,7 +10,7 @@ use hir::{ use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind, - base_db::RootQueryDb, + base_db::{RootQueryDb, salsa}, defs::Definition, documentation::docs_from_attrs, helpers::visit_file_defs, @@ -414,11 +414,13 @@ pub(crate) fn runnable_impl( let ty = def.self_ty(sema.db); let adt_name = ty.as_adt()?.name(sema.db); let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable(); - let params = if ty_args.peek().is_some() { - format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) - } else { - String::new() - }; + let params = salsa::attach(sema.db, || { + if ty_args.peek().is_some() { + format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) + } else { + String::new() + } + }); let mut test_id = format!("{}{params}", adt_name.display(sema.db, edition)); test_id.retain(|c| c != ' '); let test_id = TestId::Path(test_id); @@ -521,7 +523,9 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { let mut ty_args = ty.generic_parameters(db, display_target).peekable(); format_to!(path, "{}", name.display(db, edition)); if ty_args.peek().is_some() { - format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))); + salsa::attach(db, || { + format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))); + }); } format_to!(path, "::{}", def_name.display(db, edition)); path.retain(|c| c != ' '); diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index 86d02b4098..f45d096ac1 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -11,6 +11,7 @@ use hir::{ use ide_db::{ FilePosition, FxIndexMap, active_parameter::{callable_for_arg_list, generic_def_for_node}, + base_db::salsa, documentation::{Documentation, HasDocs}, }; use itertools::Itertools; @@ -266,12 +267,12 @@ fn signature_help_for_call( // In that case, fall back to render definitions of the respective parameters. // This is overly conservative: we do not substitute known type vars // (see FIXME in tests::impl_trait) and falling back on any unknowns. - match (p.ty().contains_unknown(), fn_params.as_deref()) { + salsa::attach(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) { (true, Some(fn_params)) => { format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target)) } _ => format_to!(buf, "{}", p.ty().display(db, display_target)), - } + }); res.push_call_param(&buf); } } diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 694ac22e19..14b6529c61 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -5,7 +5,7 @@ use arrayvec::ArrayVec; use hir::{Crate, Module, Semantics, db::HirDatabase}; use ide_db::{ FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, - base_db::{RootQueryDb, SourceDatabase, VfsPath}, + base_db::{RootQueryDb, SourceDatabase, VfsPath, salsa}, defs::{Definition, IdentClass}, documentation::Documentation, famous_defs::FamousDefs, @@ -227,30 +227,32 @@ impl StaticIndex<'_> { let id = if let Some(it) = self.def_map.get(&def) { *it } else { - let it = self.tokens.insert(TokenStaticData { - documentation: documentation_for_definition(&sema, def, scope_node), - hover: Some(hover_for_definition( - &sema, - file_id, - def, - None, - scope_node, - None, - false, - &hover_config, - edition, - display_target, - )), - definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| { - FileRange { file_id: it.file_id, range: it.focus_or_full_range() } - }), - references: vec![], - moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), - display_name: def - .name(self.db) - .map(|name| name.display(self.db, edition).to_string()), - signature: Some(def.label(self.db, display_target)), - kind: def_to_kind(self.db, def), + let it = salsa::attach(sema.db, || { + self.tokens.insert(TokenStaticData { + documentation: documentation_for_definition(&sema, def, scope_node), + hover: Some(hover_for_definition( + &sema, + file_id, + def, + None, + scope_node, + None, + false, + &hover_config, + edition, + display_target, + )), + definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map( + |it| FileRange { file_id: it.file_id, range: it.focus_or_full_range() }, + ), + references: vec![], + moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), + display_name: def + .name(self.db) + .map(|name| name.display(self.db, edition).to_string()), + signature: Some(def.label(self.db, display_target)), + kind: def_to_kind(self.db, def), + }) }); self.def_map.insert(def, it); it diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs index 63701a4d15..1eb0fd4fd8 100644 --- a/crates/ide/src/view_memory_layout.rs +++ b/crates/ide/src/view_memory_layout.rs @@ -3,6 +3,7 @@ use std::fmt; use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type}; use ide_db::{ RootDatabase, + base_db::salsa, defs::Definition, helpers::{get_definition, pick_best_token}, }; @@ -141,7 +142,9 @@ pub(crate) fn view_memory_layout( if let Ok(child_layout) = child_ty.layout(db) { nodes.push(MemoryLayoutNode { item_name: field.name(db), - typename: child_ty.display(db, display_target).to_string(), + typename: salsa::attach(db, || { + child_ty.display(db, display_target).to_string() + }), size: child_layout.size(), alignment: child_layout.align(), offset: match *field { @@ -175,7 +178,7 @@ pub(crate) fn view_memory_layout( } } - ty.layout(db) + salsa::attach(db, || ty.layout(db)) .map(|layout| { let item_name = match def { // def is a datatype @@ -188,7 +191,7 @@ pub(crate) fn view_memory_layout( def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()), }; - let typename = ty.display(db, display_target).to_string(); + let typename = salsa::attach(db, || ty.display(db, display_target).to_string()); let mut nodes = vec![MemoryLayoutNode { item_name,