table: unify::InferenceTable,
trait_env: Arc<TraitEnvironment>,
obligations: Vec<DomainGoal>,
+ last_obligations_check: Option<u32>,
result: InferenceResult,
/// The return type of the function being inferred, or the closure if we're
/// currently within one.
result: InferenceResult::default(),
table: unify::InferenceTable::new(),
obligations: Vec::default(),
+ last_obligations_check: None,
return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature
trait_env: owner
.as_generic_def_id()
}
fn resolve_obligations_as_possible(&mut self) {
+ if self.last_obligations_check == Some(self.table.revision) {
+ // no change
+ return;
+ }
+ self.last_obligations_check = Some(self.table.revision);
let obligations = mem::replace(&mut self.obligations, Vec::new());
for obligation in obligations {
let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone());
}
}
+ fn push_obligation(&mut self, o: DomainGoal) {
+ self.obligations.push(o);
+ self.last_obligations_check = None;
+ }
+
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
self.table.unify(ty1, ty2)
}
}),
ty: ty.clone(),
};
- self.obligations.push(trait_ref.cast(&Interner));
- self.obligations.push(alias_eq.cast(&Interner));
+ self.push_obligation(trait_ref.cast(&Interner));
+ self.push_obligation(alias_eq.cast(&Interner));
self.resolve_ty_as_possible(ty)
}
None => self.err_ty(),
let var = self.table.new_type_var();
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
let obligation = alias_eq.cast(&Interner);
- self.obligations.push(obligation);
+ self.push_obligation(obligation);
var
}
environment: trait_env,
});
if self.db.trait_solve(krate, goal.value).is_some() {
- self.obligations.push(implements_fn_trait);
+ self.push_obligation(implements_fn_trait);
let output_proj_ty = crate::ProjectionTy {
associated_ty_id: to_assoc_type_id(output_assoc_type),
substitution: substs,
let (predicate, binders) =
predicate.clone().subst(parameters).into_value_and_skipped_binders();
always!(binders == 0); // quantified where clauses not yet handled
- self.obligations.push(predicate.cast(&Interner));
+ self.push_obligation(predicate.cast(&Interner));
}
// add obligation for trait implementation, if this is a trait method
match def {
// construct a TraitRef
let substs =
parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
- self.obligations.push(
+ self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
.cast(&Interner),
);
pub(crate) struct InferenceTable {
pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
pub(super) type_variable_table: TypeVariableTable,
+ pub(super) revision: u32,
}
impl InferenceTable {
InferenceTable {
var_unification_table: InPlaceUnificationTable::new(),
type_variable_table: TypeVariableTable { inner: Vec::new() },
+ revision: 0,
}
}
== self.type_variable_table.is_diverging(*tv2) =>
{
// both type vars are unknown since we tried to resolve them
- self.var_unification_table.union(tv1.to_inner(), tv2.to_inner());
+ if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) {
+ self.var_unification_table.union(tv1.to_inner(), tv2.to_inner());
+ self.revision += 1;
+ }
true
}
tv.to_inner(),
TypeVarValue::Known(other.clone().intern(&Interner)),
);
+ self.revision += 1;
true
}