aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/infer.rs18
-rw-r--r--crates/hir_ty/src/infer/expr.rs6
-rw-r--r--crates/hir_ty/src/infer/path.rs2
-rw-r--r--crates/hir_ty/src/infer/unify.rs8
4 files changed, 26 insertions, 8 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index e4407ff50..497a1beb7 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -210,6 +210,7 @@ struct InferenceContext<'a> {
210 table: unify::InferenceTable, 210 table: unify::InferenceTable,
211 trait_env: Arc<TraitEnvironment>, 211 trait_env: Arc<TraitEnvironment>,
212 obligations: Vec<DomainGoal>, 212 obligations: Vec<DomainGoal>,
213 last_obligations_check: Option<u32>,
213 result: InferenceResult, 214 result: InferenceResult,
214 /// The return type of the function being inferred, or the closure if we're 215 /// The return type of the function being inferred, or the closure if we're
215 /// currently within one. 216 /// currently within one.
@@ -245,6 +246,7 @@ impl<'a> InferenceContext<'a> {
245 result: InferenceResult::default(), 246 result: InferenceResult::default(),
246 table: unify::InferenceTable::new(), 247 table: unify::InferenceTable::new(),
247 obligations: Vec::default(), 248 obligations: Vec::default(),
249 last_obligations_check: None,
248 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature 250 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature
249 trait_env: owner 251 trait_env: owner
250 .as_generic_def_id() 252 .as_generic_def_id()
@@ -334,6 +336,11 @@ impl<'a> InferenceContext<'a> {
334 } 336 }
335 337
336 fn resolve_obligations_as_possible(&mut self) { 338 fn resolve_obligations_as_possible(&mut self) {
339 if self.last_obligations_check == Some(self.table.revision) {
340 // no change
341 return;
342 }
343 self.last_obligations_check = Some(self.table.revision);
337 let obligations = mem::replace(&mut self.obligations, Vec::new()); 344 let obligations = mem::replace(&mut self.obligations, Vec::new());
338 for obligation in obligations { 345 for obligation in obligations {
339 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 346 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone());
@@ -360,6 +367,11 @@ impl<'a> InferenceContext<'a> {
360 } 367 }
361 } 368 }
362 369
370 fn push_obligation(&mut self, o: DomainGoal) {
371 self.obligations.push(o);
372 self.last_obligations_check = None;
373 }
374
363 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 375 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
364 self.table.unify(ty1, ty2) 376 self.table.unify(ty1, ty2)
365 } 377 }
@@ -408,8 +420,8 @@ impl<'a> InferenceContext<'a> {
408 }), 420 }),
409 ty: ty.clone(), 421 ty: ty.clone(),
410 }; 422 };
411 self.obligations.push(trait_ref.cast(&Interner)); 423 self.push_obligation(trait_ref.cast(&Interner));
412 self.obligations.push(alias_eq.cast(&Interner)); 424 self.push_obligation(alias_eq.cast(&Interner));
413 self.resolve_ty_as_possible(ty) 425 self.resolve_ty_as_possible(ty)
414 } 426 }
415 None => self.err_ty(), 427 None => self.err_ty(),
@@ -436,7 +448,7 @@ impl<'a> InferenceContext<'a> {
436 let var = self.table.new_type_var(); 448 let var = self.table.new_type_var();
437 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; 449 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
438 let obligation = alias_eq.cast(&Interner); 450 let obligation = alias_eq.cast(&Interner);
439 self.obligations.push(obligation); 451 self.push_obligation(obligation);
440 var 452 var
441 } 453 }
442 454
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 6279aa572..25ab3ea4c 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -99,7 +99,7 @@ impl<'a> InferenceContext<'a> {
99 environment: trait_env, 99 environment: trait_env,
100 }); 100 });
101 if self.db.trait_solve(krate, goal.value).is_some() { 101 if self.db.trait_solve(krate, goal.value).is_some() {
102 self.obligations.push(implements_fn_trait); 102 self.push_obligation(implements_fn_trait);
103 let output_proj_ty = crate::ProjectionTy { 103 let output_proj_ty = crate::ProjectionTy {
104 associated_ty_id: to_assoc_type_id(output_assoc_type), 104 associated_ty_id: to_assoc_type_id(output_assoc_type),
105 substitution: substs, 105 substitution: substs,
@@ -964,7 +964,7 @@ impl<'a> InferenceContext<'a> {
964 let (predicate, binders) = 964 let (predicate, binders) =
965 predicate.clone().subst(parameters).into_value_and_skipped_binders(); 965 predicate.clone().subst(parameters).into_value_and_skipped_binders();
966 always!(binders == 0); // quantified where clauses not yet handled 966 always!(binders == 0); // quantified where clauses not yet handled
967 self.obligations.push(predicate.cast(&Interner)); 967 self.push_obligation(predicate.cast(&Interner));
968 } 968 }
969 // add obligation for trait implementation, if this is a trait method 969 // add obligation for trait implementation, if this is a trait method
970 match def { 970 match def {
@@ -974,7 +974,7 @@ impl<'a> InferenceContext<'a> {
974 // construct a TraitRef 974 // construct a TraitRef
975 let substs = 975 let substs =
976 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 976 parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
977 self.obligations.push( 977 self.push_obligation(
978 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } 978 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
979 .cast(&Interner), 979 .cast(&Interner),
980 ); 980 );
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index cefa38509..717738789 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -258,7 +258,7 @@ impl<'a> InferenceContext<'a> {
258 .push(ty.clone()) 258 .push(ty.clone())
259 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 259 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
260 .build(); 260 .build();
261 self.obligations.push( 261 self.push_obligation(
262 TraitRef { 262 TraitRef {
263 trait_id: to_chalk_trait_id(trait_), 263 trait_id: to_chalk_trait_id(trait_),
264 substitution: trait_substs.clone(), 264 substitution: trait_substs.clone(),
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 6e7b0f5a6..5ea4b7481 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -231,6 +231,7 @@ pub(crate) struct TypeVariableData {
231pub(crate) struct InferenceTable { 231pub(crate) struct InferenceTable {
232 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, 232 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
233 pub(super) type_variable_table: TypeVariableTable, 233 pub(super) type_variable_table: TypeVariableTable,
234 pub(super) revision: u32,
234} 235}
235 236
236impl InferenceTable { 237impl InferenceTable {
@@ -238,6 +239,7 @@ impl InferenceTable {
238 InferenceTable { 239 InferenceTable {
239 var_unification_table: InPlaceUnificationTable::new(), 240 var_unification_table: InPlaceUnificationTable::new(),
240 type_variable_table: TypeVariableTable { inner: Vec::new() }, 241 type_variable_table: TypeVariableTable { inner: Vec::new() },
242 revision: 0,
241 } 243 }
242 } 244 }
243 245
@@ -360,7 +362,10 @@ impl InferenceTable {
360 == self.type_variable_table.is_diverging(*tv2) => 362 == self.type_variable_table.is_diverging(*tv2) =>
361 { 363 {
362 // both type vars are unknown since we tried to resolve them 364 // both type vars are unknown since we tried to resolve them
363 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 365 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) {
366 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner());
367 self.revision += 1;
368 }
364 true 369 true
365 } 370 }
366 371
@@ -398,6 +403,7 @@ impl InferenceTable {
398 tv.to_inner(), 403 tv.to_inner(),
399 TypeVarValue::Known(other.clone().intern(&Interner)), 404 TypeVarValue::Known(other.clone().intern(&Interner)),
400 ); 405 );
406 self.revision += 1;
401 true 407 true
402 } 408 }
403 409