aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r--crates/hir_ty/src/infer.rs141
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;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::{cast::Cast, Mutability}; 21use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
22use hir_def::{ 22use 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
39use super::{ 39use super::{
40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 TypeWalk,
42}; 41};
43use crate::{ 42use 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)]
700pub struct InferenceVar {
701 index: u32,
702}
703
704impl 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)]