Switch TraitRef in hir::TraitRef to next solver

This commit is contained in:
jackh726 2025-08-13 03:13:45 +00:00
parent 7f0ec8b69f
commit e979349978
4 changed files with 288 additions and 41 deletions

View File

@ -11,8 +11,8 @@ use base_db::Crate;
use chalk_ir::{BoundVar, Safety, TyKind}; use chalk_ir::{BoundVar, Safety, TyKind};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
GenericDefId, HasModule, ImportPathConfig, LocalFieldId, Lookup, ModuleDefId, ModuleId, GeneralConstId, GenericDefId, HasModule, ImportPathConfig, LocalFieldId, Lookup, ModuleDefId,
TraitId, ModuleId, TraitId,
db::DefDatabase, db::DefDatabase,
expr_store::{ExpressionStore, path::Path}, expr_store::{ExpressionStore, path::Path},
find_path::{self, PrefixKind}, find_path::{self, PrefixKind},
@ -38,7 +38,7 @@ use rustc_apfloat::{
}; };
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustc_type_ir::{ use rustc_type_ir::{
AliasTyKind, AliasTyKind, RegionKind,
inherent::{AdtDef, IntoKind, SliceLike}, inherent::{AdtDef, IntoKind, SliceLike},
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -61,8 +61,9 @@ use crate::{
next_solver::{ next_solver::{
BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId, BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId,
mapping::{ mapping::{
ChalkToNextSolver, convert_args_for_result, convert_const_for_result, ChalkToNextSolver, bound_var_to_lifetime_idx, bound_var_to_type_or_const_param_idx,
convert_region_for_result, convert_ty_for_result, convert_args_for_result, convert_const_for_result, convert_region_for_result,
convert_ty_for_result,
}, },
}, },
primitive, to_assoc_type_id, primitive, to_assoc_type_id,
@ -715,28 +716,56 @@ impl HirDisplay for GenericArg {
} }
} }
impl<'db> HirDisplay for crate::next_solver::GenericArg<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self.kind() {
rustc_type_ir::GenericArgKind::Type(ty) => ty.hir_fmt(f),
rustc_type_ir::GenericArgKind::Lifetime(lt) => lt.hir_fmt(f),
rustc_type_ir::GenericArgKind::Const(c) => c.hir_fmt(f),
}
}
}
impl HirDisplay for Const { impl HirDisplay for Const {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let data = self.interned(); let c = self.to_nextsolver(DbInterner::new_with(f.db, None, None));
match &data.value { c.hir_fmt(f)
ConstValue::BoundVar(idx) => idx.hir_fmt(f), }
ConstValue::InferenceVar(..) => write!(f, "#c#"), }
ConstValue::Placeholder(idx) => {
let id = from_placeholder_idx(f.db, *idx); impl<'db> HirDisplay for crate::next_solver::Const<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self.kind() {
rustc_type_ir::ConstKind::Bound(db, bound_const) => {
write!(f, "?{}.{}", db.as_u32(), bound_const.as_u32())
}
rustc_type_ir::ConstKind::Infer(..) => write!(f, "#c#"),
rustc_type_ir::ConstKind::Placeholder(idx) => {
let id = bound_var_to_type_or_const_param_idx(f.db, idx.bound);
let generics = generics(f.db, id.parent); let generics = generics(f.db, id.parent);
let param_data = &generics[id.local_id]; let param_data = &generics[id.local_id];
write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?; write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
Ok(()) Ok(())
} }
ConstValue::Concrete(c) => match &c.interned { rustc_type_ir::ConstKind::Value(const_bytes) => render_const_scalar_ns(
ConstScalar::Bytes(b, m) => render_const_scalar(f, b, m, &data.ty), f,
ConstScalar::UnevaluatedConst(c, parameters) => { &const_bytes.value.inner().0,
&const_bytes.value.inner().1,
const_bytes.ty,
),
rustc_type_ir::ConstKind::Unevaluated(unev) => {
let c = match unev.def {
SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
_ => unreachable!(),
};
write!(f, "{}", c.name(f.db))?; write!(f, "{}", c.name(f.db))?;
hir_fmt_generics(f, parameters.as_slice(Interner), c.generic_def(f.db), None)?; hir_fmt_generics_ns(f, unev.args.as_slice(), c.generic_def(f.db), None)?;
Ok(()) Ok(())
} }
ConstScalar::Unknown => f.write_char('_'), rustc_type_ir::ConstKind::Error(..) => f.write_char('_'),
}, rustc_type_ir::ConstKind::Expr(..) => write!(f, "<const-expr>"),
rustc_type_ir::ConstKind::Param(_) => write!(f, "<param>"),
} }
} }
} }
@ -1748,6 +1777,27 @@ fn hir_fmt_generics(
Ok(()) Ok(())
} }
fn hir_fmt_generics_ns<'db>(
f: &mut HirFormatter<'_>,
parameters: &[crate::next_solver::GenericArg<'db>],
generic_def: Option<hir_def::GenericDefId>,
self_: Option<crate::next_solver::Ty<'db>>,
) -> Result<(), HirDisplayError> {
if parameters.is_empty() {
return Ok(());
}
let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
if !parameters_to_write.is_empty() {
write!(f, "<")?;
hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
write!(f, ">")?;
}
Ok(())
}
fn generic_args_sans_defaults<'ga>( fn generic_args_sans_defaults<'ga>(
f: &mut HirFormatter<'_>, f: &mut HirFormatter<'_>,
generic_def: Option<hir_def::GenericDefId>, generic_def: Option<hir_def::GenericDefId>,
@ -1803,6 +1853,87 @@ fn generic_args_sans_defaults<'ga>(
} }
} }
fn hir_fmt_generic_args<'db>(
f: &mut HirFormatter<'_>,
parameters: &[crate::next_solver::GenericArg<'db>],
generic_def: Option<hir_def::GenericDefId>,
self_: Option<crate::next_solver::Ty<'db>>,
) -> Result<(), HirDisplayError> {
if parameters.is_empty() {
return Ok(());
}
let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
if !parameters_to_write.is_empty() {
write!(f, "<")?;
hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
write!(f, ">")?;
}
Ok(())
}
fn generic_args_sans_defaults_ns<'ga, 'db>(
f: &mut HirFormatter<'_>,
generic_def: Option<hir_def::GenericDefId>,
parameters: &'ga [crate::next_solver::GenericArg<'db>],
) -> &'ga [crate::next_solver::GenericArg<'db>] {
let interner = DbInterner::new_with(f.db, Some(f.krate()), None);
if f.display_kind.is_source_code() || f.omit_verbose_types() {
match generic_def
.map(|generic_def_id| f.db.generic_defaults(generic_def_id))
.filter(|it| !it.is_empty())
{
None => parameters,
Some(default_parameters) => {
let should_show = |arg: &crate::next_solver::GenericArg<'db>, i: usize| {
let is_err = |arg: &crate::next_solver::GenericArg<'db>| match arg.kind() {
rustc_type_ir::GenericArgKind::Lifetime(it) => {
matches!(it.kind(), RegionKind::ReError(..))
}
rustc_type_ir::GenericArgKind::Type(it) => {
matches!(it.kind(), rustc_type_ir::TyKind::Error(..))
}
rustc_type_ir::GenericArgKind::Const(it) => {
matches!(it.kind(), rustc_type_ir::ConstKind::Error(..),)
}
};
// if the arg is error like, render it to inform the user
if is_err(arg) {
return true;
}
// otherwise, if the arg is equal to the param default, hide it (unless the
// default is an error which can happen for the trait Self type)
match default_parameters.get(i) {
None => true,
Some(default_parameter) => {
// !is_err(default_parameter.skip_binders())
// &&
arg != &default_parameter
.clone()
.substitute(
Interner,
&convert_args_for_result(interner, &parameters[..i]),
)
.to_nextsolver(interner)
}
}
};
let mut default_from = 0;
for (i, parameter) in parameters.iter().enumerate() {
if should_show(parameter, i) {
default_from = i + 1;
}
}
&parameters[0..default_from]
}
}
} else {
parameters
}
}
fn hir_fmt_generic_arguments( fn hir_fmt_generic_arguments(
f: &mut HirFormatter<'_>, f: &mut HirFormatter<'_>,
parameters: &[GenericArg], parameters: &[GenericArg],
@ -1827,6 +1958,30 @@ fn hir_fmt_generic_arguments(
Ok(()) Ok(())
} }
fn hir_fmt_generic_arguments_ns<'db>(
f: &mut HirFormatter<'_>,
parameters: &[crate::next_solver::GenericArg<'db>],
self_: Option<crate::next_solver::Ty<'db>>,
) -> Result<(), HirDisplayError> {
let mut first = true;
let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some());
let (ty_or_const, lifetimes) = match lifetime_offset {
Some(offset) => parameters.split_at(offset),
None => (parameters, &[][..]),
};
for generic_arg in lifetimes.iter().chain(ty_or_const) {
if !mem::take(&mut first) {
write!(f, ", ")?;
}
match self_ {
self_ @ Some(_) if generic_arg.ty() == self_ => write!(f, "Self")?,
_ => generic_arg.hir_fmt(f)?,
}
}
Ok(())
}
impl HirDisplay for CallableSig { impl HirDisplay for CallableSig {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self; let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self;
@ -2067,6 +2222,20 @@ impl HirDisplay for TraitRef {
} }
} }
impl<'db> HirDisplay for crate::next_solver::TraitRef<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let trait_ = match self.def_id {
SolverDefId::TraitId(id) => id,
_ => unreachable!(),
};
f.start_location_link(trait_.into());
write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
f.end_location_link();
let substs = self.args.as_slice();
hir_fmt_generic_args(f, &substs[1..], None, substs[0].ty())
}
}
impl HirDisplay for WhereClause { impl HirDisplay for WhereClause {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
if f.should_truncate() { if f.should_truncate() {
@ -2147,6 +2316,35 @@ impl HirDisplay for LifetimeData {
} }
} }
impl<'db> HirDisplay for crate::next_solver::Region<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self.kind() {
rustc_type_ir::RegionKind::RePlaceholder(idx) => {
let id = bound_var_to_lifetime_idx(f.db, idx.bound.var);
let generics = generics(f.db, id.parent);
let param_data = &generics[id.local_id];
write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
Ok(())
}
rustc_type_ir::RegionKind::ReBound(db, idx) => {
write!(f, "?{}.{}", db.as_u32(), idx.var.as_u32())
}
rustc_type_ir::RegionKind::ReVar(_) => write!(f, "_"),
rustc_type_ir::RegionKind::ReStatic => write!(f, "'static"),
rustc_type_ir::RegionKind::ReError(..) => {
if cfg!(test) {
write!(f, "'?")
} else {
write!(f, "'_")
}
}
rustc_type_ir::RegionKind::ReErased => write!(f, "'<erased>"),
rustc_type_ir::RegionKind::ReEarlyParam(_) => write!(f, "<param>"),
rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, "<late-param>"),
}
}
}
impl HirDisplay for DomainGoal { impl HirDisplay for DomainGoal {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self { match self {

View File

@ -35,6 +35,29 @@ impl<'db> std::fmt::Debug for GenericArg<'db> {
} }
} }
impl<'db> GenericArg<'db> {
pub fn ty(self) -> Option<Ty<'db>> {
match self.kind() {
GenericArgKind::Type(ty) => Some(ty),
_ => None,
}
}
pub fn expect_ty(self) -> Ty<'db> {
match self.kind() {
GenericArgKind::Type(ty) => ty,
_ => panic!("Expected ty, got {:?}", self),
}
}
pub fn region(self) -> Option<Region<'db>> {
match self.kind() {
GenericArgKind::Lifetime(r) => Some(r),
_ => None,
}
}
}
impl<'db> From<Term<'db>> for GenericArg<'db> { impl<'db> From<Term<'db>> for GenericArg<'db> {
fn from(value: Term<'db>) -> Self { fn from(value: Term<'db>) -> Self {
match value { match value {

View File

@ -18,13 +18,14 @@ use rustc_type_ir::{
shift_vars, shift_vars,
solve::Goal, solve::Goal,
}; };
use salsa::plumbing::AsId; use salsa::plumbing::FromId;
use salsa::{Id, plumbing::AsId};
use crate::{ use crate::{
ConcreteConst, ConstScalar, ImplTraitId, Interner, MemoryMap, ConcreteConst, ConstScalar, ImplTraitId, Interner, MemoryMap,
db::{ db::{
HirDatabase, InternedClosureId, InternedCoroutineId, InternedOpaqueTyId, HirDatabase, InternedClosureId, InternedCoroutineId, InternedLifetimeParamId,
InternedTypeOrConstParamId, InternedOpaqueTyId, InternedTypeOrConstParamId,
}, },
from_assoc_type_id, from_chalk_trait_id, from_assoc_type_id, from_chalk_trait_id,
mapping::ToChalk, mapping::ToChalk,
@ -55,6 +56,24 @@ pub fn to_placeholder_idx<T: Clone + std::fmt::Debug>(
} }
} }
pub fn bound_var_to_type_or_const_param_idx(
db: &dyn HirDatabase,
var: rustc_type_ir::BoundVar,
) -> TypeOrConstParamId {
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
let interned_id = InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(var.as_u32()) });
interned_id.loc(db)
}
pub fn bound_var_to_lifetime_idx(
db: &dyn HirDatabase,
var: rustc_type_ir::BoundVar,
) -> LifetimeParamId {
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
let interned_id = InternedLifetimeParamId::from_id(unsafe { Id::from_index(var.as_u32()) });
interned_id.loc(db)
}
pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>( pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
interner: DbInterner<'db>, interner: DbInterner<'db>,
binder: rustc_type_ir::Binder<DbInterner<'db>, T>, binder: rustc_type_ir::Binder<DbInterner<'db>, T>,

View File

@ -115,7 +115,7 @@ pub use crate::{
VisibleTraits, VisibleTraits,
}, },
}; };
use rustc_type_ir::inherent::IntoKind; use rustc_type_ir::inherent::{IntoKind, SliceLike};
// Be careful with these re-exports. // Be careful with these re-exports.
// //
@ -4513,14 +4513,20 @@ impl Impl {
} }
pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> { pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
let trait_ref = db.impl_trait(self.id)?; let trait_ref = db.impl_trait_ns(self.id)?;
let id = trait_ref.skip_binders().hir_trait_id(); let id = trait_ref.skip_binder().def_id;
let id = match id {
SolverDefId::TraitId(id) => id,
_ => unreachable!(),
};
Some(Trait { id }) Some(Trait { id })
} }
pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> { pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> {
let interner = DbInterner::new_with(db, None, None);
let substs = TyBuilder::placeholder_subst(db, self.id); let substs = TyBuilder::placeholder_subst(db, self.id);
let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs); let trait_ref =
db.impl_trait(self.id)?.substitute(Interner, &substs).to_nextsolver(interner);
let resolver = self.id.resolver(db); let resolver = self.id.resolver(db);
Some(TraitRef::new_with_resolver(db, &resolver, trait_ref)) Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
} }
@ -4589,7 +4595,7 @@ impl Impl {
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TraitRef<'db> { pub struct TraitRef<'db> {
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
trait_ref: hir_ty::TraitRef, trait_ref: hir_ty::next_solver::TraitRef<'db>,
_pd: PhantomCovariantLifetime<'db>, _pd: PhantomCovariantLifetime<'db>,
} }
@ -4597,7 +4603,7 @@ impl<'db> TraitRef<'db> {
pub(crate) fn new_with_resolver( pub(crate) fn new_with_resolver(
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
resolver: &Resolver<'_>, resolver: &Resolver<'_>,
trait_ref: hir_ty::TraitRef, trait_ref: hir_ty::next_solver::TraitRef<'db>,
) -> Self { ) -> Self {
let env = resolver let env = resolver
.generic_def() .generic_def()
@ -4606,25 +4612,26 @@ impl<'db> TraitRef<'db> {
} }
pub fn trait_(&self) -> Trait { pub fn trait_(&self) -> Trait {
let id = self.trait_ref.hir_trait_id(); let id = match self.trait_ref.def_id {
SolverDefId::TraitId(id) => id,
_ => unreachable!(),
};
Trait { id } Trait { id }
} }
pub fn self_ty(&self) -> Type<'_> { pub fn self_ty(&self) -> TypeNs<'_> {
let ty = self.trait_ref.self_type_parameter(Interner); let ty = self.trait_ref.self_ty();
Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } TypeNs { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() }
} }
/// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
/// first argument is the `Self` type. /// first argument is the `Self` type.
pub fn get_type_argument(&self, idx: usize) -> Option<Type<'db>> { pub fn get_type_argument(&self, idx: usize) -> Option<TypeNs<'db>> {
self.trait_ref self.trait_ref.args.as_slice().get(idx).and_then(|arg| arg.ty()).map(|ty| TypeNs {
.substitution env: self.env.clone(),
.as_slice(Interner) ty,
.get(idx) _pd: PhantomCovariantLifetime::new(),
.and_then(|arg| arg.ty(Interner)) })
.cloned()
.map(|ty| Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() })
} }
} }