diff options
Diffstat (limited to 'crates/hir_ty')
| -rw-r--r-- | crates/hir_ty/src/infer.rs | 18 | ||||
| -rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 6 | ||||
| -rw-r--r-- | crates/hir_ty/src/infer/path.rs | 2 | ||||
| -rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 8 |
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 { | |||
| 231 | pub(crate) struct InferenceTable { | 231 | pub(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 | ||
| 236 | impl InferenceTable { | 237 | impl 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 | ||
