Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/unify.rs')
-rw-r--r--crates/hir-ty/src/infer/unify.rs74
1 files changed, 71 insertions, 3 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 709760b64f..1d0150d850 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -10,15 +10,16 @@ use chalk_solve::infer::ParameterEnaVariableExt;
use either::Either;
use ena::unify::UnifyKey;
use hir_expand::name;
+use smallvec::SmallVec;
use triomphe::Arc;
use super::{InferOk, InferResult, InferenceContext, TypeError};
use crate::{
consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
- DebruijnIndex, GenericArg, GenericArgData, Goal, Guidance, InEnvironment, InferenceVar,
- Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution,
- TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
+ DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
+ InferenceVar, Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution,
+ Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause,
};
impl InferenceContext<'_> {
@@ -31,6 +32,72 @@ impl InferenceContext<'_> {
{
self.table.canonicalize(t)
}
+
+ pub(super) fn clauses_for_self_ty(
+ &mut self,
+ self_ty: InferenceVar,
+ ) -> SmallVec<[WhereClause; 4]> {
+ self.table.resolve_obligations_as_possible();
+
+ let root = self.table.var_unification_table.inference_var_root(self_ty);
+ let pending_obligations = mem::take(&mut self.table.pending_obligations);
+ let obligations = pending_obligations
+ .iter()
+ .filter_map(|obligation| match obligation.value.value.goal.data(Interner) {
+ GoalData::DomainGoal(DomainGoal::Holds(
+ clause @ WhereClause::AliasEq(AliasEq {
+ alias: AliasTy::Projection(projection),
+ ..
+ }),
+ )) => {
+ let projection_self = projection.self_type_parameter(self.db);
+ let uncanonical = chalk_ir::Substitute::apply(
+ &obligation.free_vars,
+ projection_self,
+ Interner,
+ );
+ if matches!(
+ self.resolve_ty_shallow(&uncanonical).kind(Interner),
+ TyKind::InferenceVar(iv, TyVariableKind::General) if *iv == root,
+ ) {
+ Some(chalk_ir::Substitute::apply(
+ &obligation.free_vars,
+ clause.clone(),
+ Interner,
+ ))
+ } else {
+ None
+ }
+ }
+ GoalData::DomainGoal(DomainGoal::Holds(
+ clause @ WhereClause::Implemented(trait_ref),
+ )) => {
+ let trait_ref_self = trait_ref.self_type_parameter(Interner);
+ let uncanonical = chalk_ir::Substitute::apply(
+ &obligation.free_vars,
+ trait_ref_self,
+ Interner,
+ );
+ if matches!(
+ self.resolve_ty_shallow(&uncanonical).kind(Interner),
+ TyKind::InferenceVar(iv, TyVariableKind::General) if *iv == root,
+ ) {
+ Some(chalk_ir::Substitute::apply(
+ &obligation.free_vars,
+ clause.clone(),
+ Interner,
+ ))
+ } else {
+ None
+ }
+ }
+ _ => None,
+ })
+ .collect();
+ self.table.pending_obligations = pending_obligations;
+
+ obligations
+ }
}
#[derive(Debug, Clone)]
@@ -457,6 +524,7 @@ impl<'a> InferenceTable<'a> {
}
/// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
+ #[tracing::instrument(skip_all)]
pub(crate) fn unify<T: ?Sized + Zip<Interner>>(&mut self, ty1: &T, ty2: &T) -> bool {
let result = match self.try_unify(ty1, ty2) {
Ok(r) => r,