diff options
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 141 |
1 files changed, 64 insertions, 77 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 1c3faf5cb..bf2da2d4a 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,7 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::{cast::Cast, Mutability}; | 21 | use chalk_ir::{cast::Cast, DebruijnIndex, Mutability}; |
22 | use hir_def::{ | 22 | use hir_def::{ |
23 | body::Body, | 23 | body::Body, |
24 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -38,11 +38,11 @@ use syntax::SmolStr; | |||
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, | 40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, |
41 | TypeWalk, | ||
42 | }; | 41 | }; |
43 | use crate::{ | 42 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 43 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
45 | to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, | 44 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, |
45 | TyBuilder, TyExt, TyKind, | ||
46 | }; | 46 | }; |
47 | 47 | ||
48 | // This lint has a false positive here. See the link below for details. | 48 | // This lint has a false positive here. See the link below for details. |
@@ -131,10 +131,7 @@ pub struct InferenceResult { | |||
131 | method_resolutions: FxHashMap<ExprId, FunctionId>, | 131 | method_resolutions: FxHashMap<ExprId, FunctionId>, |
132 | /// For each field access expr, records the field it resolves to. | 132 | /// For each field access expr, records the field it resolves to. |
133 | field_resolutions: FxHashMap<ExprId, FieldId>, | 133 | field_resolutions: FxHashMap<ExprId, FieldId>, |
134 | /// For each field in record literal, records the field it resolves to. | 134 | /// For each struct literal or pattern, records the variant it resolves to. |
135 | record_field_resolutions: FxHashMap<ExprId, FieldId>, | ||
136 | record_pat_field_resolutions: FxHashMap<PatId, FieldId>, | ||
137 | /// For each struct literal, records the variant it resolves to. | ||
138 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, | 135 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, |
139 | /// For each associated item record what it resolves to | 136 | /// For each associated item record what it resolves to |
140 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, | 137 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, |
@@ -153,12 +150,6 @@ impl InferenceResult { | |||
153 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { | 150 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { |
154 | self.field_resolutions.get(&expr).copied() | 151 | self.field_resolutions.get(&expr).copied() |
155 | } | 152 | } |
156 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> { | ||
157 | self.record_field_resolutions.get(&expr).copied() | ||
158 | } | ||
159 | pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> { | ||
160 | self.record_pat_field_resolutions.get(&pat).copied() | ||
161 | } | ||
162 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { | 153 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { |
163 | self.variant_resolutions.get(&id.into()).copied() | 154 | self.variant_resolutions.get(&id.into()).copied() |
164 | } | 155 | } |
@@ -332,7 +323,7 @@ impl<'a> InferenceContext<'a> { | |||
332 | } | 323 | } |
333 | 324 | ||
334 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { | 325 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { |
335 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | 326 | fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST) |
336 | } | 327 | } |
337 | 328 | ||
338 | fn resolve_obligations_as_possible(&mut self) { | 329 | fn resolve_obligations_as_possible(&mut self) { |
@@ -345,17 +336,24 @@ impl<'a> InferenceContext<'a> { | |||
345 | self.last_obligations_check = Some(self.table.revision); | 336 | self.last_obligations_check = Some(self.table.revision); |
346 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 337 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
347 | for obligation in obligations { | 338 | for obligation in obligations { |
348 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); | 339 | let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone()); |
349 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 340 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
350 | let solution = | 341 | let solution = |
351 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 342 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
352 | 343 | ||
353 | match solution { | 344 | match solution { |
354 | Some(Solution::Unique(substs)) => { | 345 | Some(Solution::Unique(canonical_subst)) => { |
355 | canonicalized.apply_solution(self, substs.0); | 346 | canonicalized.apply_solution( |
347 | self, | ||
348 | Canonical { | ||
349 | binders: canonical_subst.binders, | ||
350 | // FIXME: handle constraints | ||
351 | value: canonical_subst.value.subst, | ||
352 | }, | ||
353 | ); | ||
356 | } | 354 | } |
357 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | 355 | Some(Solution::Ambig(Guidance::Definite(substs))) => { |
358 | canonicalized.apply_solution(self, substs.0); | 356 | canonicalized.apply_solution(self, substs); |
359 | self.obligations.push(obligation); | 357 | self.obligations.push(obligation); |
360 | } | 358 | } |
361 | Some(_) => { | 359 | Some(_) => { |
@@ -436,12 +434,16 @@ impl<'a> InferenceContext<'a> { | |||
436 | /// to do it as well. | 434 | /// to do it as well. |
437 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 435 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
438 | let ty = self.resolve_ty_as_possible(ty); | 436 | let ty = self.resolve_ty_as_possible(ty); |
439 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 437 | fold_tys( |
440 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | 438 | ty, |
441 | self.normalize_projection_ty(proj_ty.clone()) | 439 | |ty, _| match ty.kind(&Interner) { |
442 | } | 440 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { |
443 | _ => ty, | 441 | self.normalize_projection_ty(proj_ty.clone()) |
444 | }) | 442 | } |
443 | _ => ty, | ||
444 | }, | ||
445 | DebruijnIndex::INNERMOST, | ||
446 | ) | ||
445 | } | 447 | } |
446 | 448 | ||
447 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | 449 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |
@@ -489,36 +491,13 @@ impl<'a> InferenceContext<'a> { | |||
489 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 491 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
490 | let substs = generics.type_params_subst(self.db); | 492 | let substs = generics.type_params_subst(self.db); |
491 | let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); | 493 | let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); |
492 | match unresolved { | 494 | self.resolve_variant_on_alias(ty, unresolved, path) |
493 | None => { | ||
494 | let variant = ty_variant(&ty); | ||
495 | (ty, variant) | ||
496 | } | ||
497 | Some(1) => { | ||
498 | let segment = path.mod_path().segments().last().unwrap(); | ||
499 | // this could be an enum variant or associated type | ||
500 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
501 | let enum_data = self.db.enum_data(enum_id); | ||
502 | if let Some(local_id) = enum_data.variant(segment) { | ||
503 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
504 | return (ty, Some(variant.into())); | ||
505 | } | ||
506 | } | ||
507 | // FIXME potentially resolve assoc type | ||
508 | (self.err_ty(), None) | ||
509 | } | ||
510 | Some(_) => { | ||
511 | // FIXME diagnostic | ||
512 | (self.err_ty(), None) | ||
513 | } | ||
514 | } | ||
515 | } | 495 | } |
516 | TypeNs::TypeAliasId(it) => { | 496 | TypeNs::TypeAliasId(it) => { |
517 | let ty = TyBuilder::def_ty(self.db, it.into()) | 497 | let ty = TyBuilder::def_ty(self.db, it.into()) |
518 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 498 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
519 | .build(); | 499 | .build(); |
520 | let variant = ty_variant(&ty); | 500 | self.resolve_variant_on_alias(ty, unresolved, path) |
521 | forbid_unresolved_segments((ty, variant), unresolved) | ||
522 | } | 501 | } |
523 | TypeNs::AdtSelfType(_) => { | 502 | TypeNs::AdtSelfType(_) => { |
524 | // FIXME this could happen in array size expressions, once we're checking them | 503 | // FIXME this could happen in array size expressions, once we're checking them |
@@ -545,16 +524,43 @@ impl<'a> InferenceContext<'a> { | |||
545 | (TyKind::Error.intern(&Interner), None) | 524 | (TyKind::Error.intern(&Interner), None) |
546 | } | 525 | } |
547 | } | 526 | } |
527 | } | ||
548 | 528 | ||
549 | fn ty_variant(ty: &Ty) -> Option<VariantId> { | 529 | fn resolve_variant_on_alias( |
550 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { | 530 | &mut self, |
551 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | 531 | ty: Ty, |
552 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | 532 | unresolved: Option<usize>, |
553 | AdtId::EnumId(_) => { | 533 | path: &Path, |
554 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | 534 | ) -> (Ty, Option<VariantId>) { |
555 | None | 535 | match unresolved { |
536 | None => { | ||
537 | let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id { | ||
538 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | ||
539 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | ||
540 | AdtId::EnumId(_) => { | ||
541 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | ||
542 | None | ||
543 | } | ||
544 | }); | ||
545 | (ty, variant) | ||
546 | } | ||
547 | Some(1) => { | ||
548 | let segment = path.mod_path().segments().last().unwrap(); | ||
549 | // this could be an enum variant or associated type | ||
550 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
551 | let enum_data = self.db.enum_data(enum_id); | ||
552 | if let Some(local_id) = enum_data.variant(segment) { | ||
553 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
554 | return (ty, Some(variant.into())); | ||
555 | } | ||
556 | } | 556 | } |
557 | }) | 557 | // FIXME potentially resolve assoc type |
558 | (self.err_ty(), None) | ||
559 | } | ||
560 | Some(_) => { | ||
561 | // FIXME diagnostic | ||
562 | (self.err_ty(), None) | ||
563 | } | ||
558 | } | 564 | } |
559 | } | 565 | } |
560 | 566 | ||
@@ -692,25 +698,6 @@ impl<'a> InferenceContext<'a> { | |||
692 | } | 698 | } |
693 | } | 699 | } |
694 | 700 | ||
695 | /// The kinds of placeholders we need during type inference. There's separate | ||
696 | /// values for general types, and for integer and float variables. The latter | ||
697 | /// two are used for inference of literal values (e.g. `100` could be one of | ||
698 | /// several integer types). | ||
699 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | ||
700 | pub struct InferenceVar { | ||
701 | index: u32, | ||
702 | } | ||
703 | |||
704 | impl InferenceVar { | ||
705 | fn to_inner(self) -> unify::TypeVarId { | ||
706 | unify::TypeVarId(self.index) | ||
707 | } | ||
708 | |||
709 | fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self { | ||
710 | InferenceVar { index } | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /// When inferring an expression, we propagate downward whatever type hint we | 701 | /// When inferring an expression, we propagate downward whatever type hint we |
715 | /// are able in the form of an `Expectation`. | 702 | /// are able in the form of an `Expectation`. |
716 | #[derive(Clone, PartialEq, Eq, Debug)] | 703 | #[derive(Clone, PartialEq, Eq, Debug)] |