diff options
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 84 |
1 files changed, 15 insertions, 69 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 7898740be..97e7c5f8c 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -14,7 +14,7 @@ | |||
14 | //! the `ena` crate, which is extracted from rustc. | 14 | //! the `ena` crate, which is extracted from rustc. |
15 | 15 | ||
16 | use std::borrow::Cow; | 16 | use std::borrow::Cow; |
17 | use std::mem; | 17 | |
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
@@ -27,8 +27,8 @@ use hir_def::{ | |||
27 | path::{path, Path}, | 27 | path::{path, Path}, |
28 | resolver::{HasResolver, Resolver, TypeNs}, | 28 | resolver::{HasResolver, Resolver, TypeNs}, |
29 | type_ref::TypeRef, | 29 | type_ref::TypeRef, |
30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, | 30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup, |
31 | TypeAliasId, VariantId, | 31 | TraitId, TypeAliasId, VariantId, |
32 | }; | 32 | }; |
33 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 33 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
34 | use la_arena::ArenaMap; | 34 | use la_arena::ArenaMap; |
@@ -36,13 +36,11 @@ use rustc_hash::FxHashMap; | |||
36 | use stdx::impl_from; | 36 | use stdx::impl_from; |
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; |
40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, | ||
41 | }; | ||
42 | use crate::{ | 40 | use crate::{ |
43 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, | 41 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
44 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, | 42 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, |
45 | TyBuilder, TyExt, TyKind, | 43 | TyKind, |
46 | }; | 44 | }; |
47 | 45 | ||
48 | // This lint has a false positive here. See the link below for details. | 46 | // This lint has a false positive here. See the link below for details. |
@@ -227,8 +225,6 @@ struct InferenceContext<'a> { | |||
227 | resolver: Resolver, | 225 | resolver: Resolver, |
228 | table: unify::InferenceTable<'a>, | 226 | table: unify::InferenceTable<'a>, |
229 | trait_env: Arc<TraitEnvironment>, | 227 | trait_env: Arc<TraitEnvironment>, |
230 | obligations: Vec<DomainGoal>, | ||
231 | last_obligations_check: Option<u32>, | ||
232 | result: InferenceResult, | 228 | result: InferenceResult, |
233 | /// The return type of the function being inferred, or the closure if we're | 229 | /// The return type of the function being inferred, or the closure if we're |
234 | /// currently within one. | 230 | /// currently within one. |
@@ -260,15 +256,15 @@ fn find_breakable<'c>( | |||
260 | 256 | ||
261 | impl<'a> InferenceContext<'a> { | 257 | impl<'a> InferenceContext<'a> { |
262 | fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self { | 258 | fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self { |
263 | let trait_env = | 259 | let krate = owner.module(db.upcast()).krate(); |
264 | owner.as_generic_def_id().map_or_else(Default::default, |d| db.trait_environment(d)); | 260 | let trait_env = owner |
261 | .as_generic_def_id() | ||
262 | .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d)); | ||
265 | InferenceContext { | 263 | InferenceContext { |
266 | result: InferenceResult::default(), | 264 | result: InferenceResult::default(), |
267 | table: unify::InferenceTable::new(db, trait_env.clone()), | 265 | table: unify::InferenceTable::new(db, trait_env.clone()), |
268 | obligations: Vec::default(), | ||
269 | last_obligations_check: None, | ||
270 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature | ||
271 | trait_env, | 266 | trait_env, |
267 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature | ||
272 | db, | 268 | db, |
273 | owner, | 269 | owner, |
274 | body: db.body(owner), | 270 | body: db.body(owner), |
@@ -284,6 +280,7 @@ impl<'a> InferenceContext<'a> { | |||
284 | 280 | ||
285 | fn resolve_all(mut self) -> InferenceResult { | 281 | fn resolve_all(mut self) -> InferenceResult { |
286 | // FIXME resolve obligations as well (use Guidance if necessary) | 282 | // FIXME resolve obligations as well (use Guidance if necessary) |
283 | self.table.resolve_obligations_as_possible(); | ||
287 | 284 | ||
288 | // make sure diverging type variables are marked as such | 285 | // make sure diverging type variables are marked as such |
289 | self.table.propagate_diverging_flag(); | 286 | self.table.propagate_diverging_flag(); |
@@ -357,44 +354,11 @@ impl<'a> InferenceContext<'a> { | |||
357 | } | 354 | } |
358 | 355 | ||
359 | fn resolve_obligations_as_possible(&mut self) { | 356 | fn resolve_obligations_as_possible(&mut self) { |
360 | let _span = profile::span("resolve_obligations_as_possible"); | 357 | self.table.resolve_obligations_as_possible(); |
361 | |||
362 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | ||
363 | for obligation in obligations { | ||
364 | let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone()); | ||
365 | let canonicalized = self.canonicalize(in_env); | ||
366 | let solution = | ||
367 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | ||
368 | |||
369 | match solution { | ||
370 | Some(Solution::Unique(canonical_subst)) => { | ||
371 | canonicalized.apply_solution( | ||
372 | self, | ||
373 | Canonical { | ||
374 | binders: canonical_subst.binders, | ||
375 | // FIXME: handle constraints | ||
376 | value: canonical_subst.value.subst, | ||
377 | }, | ||
378 | ); | ||
379 | } | ||
380 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
381 | canonicalized.apply_solution(self, substs); | ||
382 | self.obligations.push(obligation); | ||
383 | } | ||
384 | Some(_) => { | ||
385 | // FIXME use this when trying to resolve everything at the end | ||
386 | self.obligations.push(obligation); | ||
387 | } | ||
388 | None => { | ||
389 | // FIXME obligation cannot be fulfilled => diagnostic | ||
390 | } | ||
391 | }; | ||
392 | } | ||
393 | } | 358 | } |
394 | 359 | ||
395 | fn push_obligation(&mut self, o: DomainGoal) { | 360 | fn push_obligation(&mut self, o: DomainGoal) { |
396 | self.obligations.push(o); | 361 | self.table.register_obligation(o.cast(&Interner)); |
397 | self.last_obligations_check = None; | ||
398 | } | 362 | } |
399 | 363 | ||
400 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 364 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
@@ -467,25 +431,7 @@ impl<'a> InferenceContext<'a> { | |||
467 | /// call). `make_ty` handles this already, but e.g. for field types we need | 431 | /// call). `make_ty` handles this already, but e.g. for field types we need |
468 | /// to do it as well. | 432 | /// to do it as well. |
469 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 433 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
470 | let ty = self.resolve_ty_as_possible(ty); | 434 | self.table.normalize_associated_types_in(ty) |
471 | fold_tys( | ||
472 | ty, | ||
473 | |ty, _| match ty.kind(&Interner) { | ||
474 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | ||
475 | self.normalize_projection_ty(proj_ty.clone()) | ||
476 | } | ||
477 | _ => ty, | ||
478 | }, | ||
479 | DebruijnIndex::INNERMOST, | ||
480 | ) | ||
481 | } | ||
482 | |||
483 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | ||
484 | let var = self.table.new_type_var(); | ||
485 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; | ||
486 | let obligation = alias_eq.cast(&Interner); | ||
487 | self.push_obligation(obligation); | ||
488 | var | ||
489 | } | 435 | } |
490 | 436 | ||
491 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { | 437 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { |