diff options
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 165 |
1 files changed, 76 insertions, 89 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 1b1d4458c..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}, |
@@ -37,12 +37,12 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{DomainGoal, Guidance, Solution}, | 40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, |
41 | InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, 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. |
@@ -120,7 +120,7 @@ struct InternedStandardTypes { | |||
120 | 120 | ||
121 | impl Default for InternedStandardTypes { | 121 | impl Default for InternedStandardTypes { |
122 | fn default() -> Self { | 122 | fn default() -> Self { |
123 | InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) } | 123 | InternedStandardTypes { unknown: TyKind::Error.intern(&Interner) } |
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
@@ -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 | } |
@@ -247,7 +238,7 @@ impl<'a> InferenceContext<'a> { | |||
247 | table: unify::InferenceTable::new(), | 238 | table: unify::InferenceTable::new(), |
248 | obligations: Vec::default(), | 239 | obligations: Vec::default(), |
249 | last_obligations_check: None, | 240 | last_obligations_check: None, |
250 | return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature | 241 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature |
251 | trait_env: owner | 242 | trait_env: owner |
252 | .as_generic_def_id() | 243 | .as_generic_def_id() |
253 | .map_or_else(Default::default, |d| db.trait_environment(d)), | 244 | .map_or_else(Default::default, |d| db.trait_environment(d)), |
@@ -261,7 +252,7 @@ impl<'a> InferenceContext<'a> { | |||
261 | } | 252 | } |
262 | 253 | ||
263 | fn err_ty(&self) -> Ty { | 254 | fn err_ty(&self) -> Ty { |
264 | TyKind::Unknown.intern(&Interner) | 255 | TyKind::Error.intern(&Interner) |
265 | } | 256 | } |
266 | 257 | ||
267 | fn resolve_all(mut self) -> InferenceResult { | 258 | fn resolve_all(mut self) -> InferenceResult { |
@@ -326,13 +317,13 @@ impl<'a> InferenceContext<'a> { | |||
326 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 317 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
327 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 318 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
328 | match ty.kind(&Interner) { | 319 | match ty.kind(&Interner) { |
329 | TyKind::Unknown => self.table.new_type_var(), | 320 | TyKind::Error => self.table.new_type_var(), |
330 | _ => ty, | 321 | _ => ty, |
331 | } | 322 | } |
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 { |
@@ -470,55 +472,32 @@ impl<'a> InferenceContext<'a> { | |||
470 | TypeNs::AdtId(AdtId::StructId(strukt)) => { | 472 | TypeNs::AdtId(AdtId::StructId(strukt)) => { |
471 | let substs = ctx.substs_from_path(path, strukt.into(), true); | 473 | let substs = ctx.substs_from_path(path, strukt.into(), true); |
472 | let ty = self.db.ty(strukt.into()); | 474 | let ty = self.db.ty(strukt.into()); |
473 | let ty = self.insert_type_vars(ty.subst(&substs)); | 475 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
474 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) | 476 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) |
475 | } | 477 | } |
476 | TypeNs::AdtId(AdtId::UnionId(u)) => { | 478 | TypeNs::AdtId(AdtId::UnionId(u)) => { |
477 | let substs = ctx.substs_from_path(path, u.into(), true); | 479 | let substs = ctx.substs_from_path(path, u.into(), true); |
478 | let ty = self.db.ty(u.into()); | 480 | let ty = self.db.ty(u.into()); |
479 | let ty = self.insert_type_vars(ty.subst(&substs)); | 481 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
480 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) | 482 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) |
481 | } | 483 | } |
482 | TypeNs::EnumVariantId(var) => { | 484 | TypeNs::EnumVariantId(var) => { |
483 | let substs = ctx.substs_from_path(path, var.into(), true); | 485 | let substs = ctx.substs_from_path(path, var.into(), true); |
484 | let ty = self.db.ty(var.parent.into()); | 486 | let ty = self.db.ty(var.parent.into()); |
485 | let ty = self.insert_type_vars(ty.subst(&substs)); | 487 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
486 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) | 488 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) |
487 | } | 489 | } |
488 | TypeNs::SelfType(impl_id) => { | 490 | TypeNs::SelfType(impl_id) => { |
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).subst(&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 |
@@ -542,19 +521,46 @@ impl<'a> InferenceContext<'a> { | |||
542 | result | 521 | result |
543 | } else { | 522 | } else { |
544 | // FIXME diagnostic | 523 | // FIXME diagnostic |
545 | (TyKind::Unknown.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)] |
@@ -755,7 +742,7 @@ impl Expectation { | |||
755 | fn none() -> Self { | 742 | fn none() -> Self { |
756 | Expectation { | 743 | Expectation { |
757 | // FIXME | 744 | // FIXME |
758 | ty: TyKind::Unknown.intern(&Interner), | 745 | ty: TyKind::Error.intern(&Interner), |
759 | rvalue_hint: false, | 746 | rvalue_hint: false, |
760 | } | 747 | } |
761 | } | 748 | } |
@@ -763,7 +750,7 @@ impl Expectation { | |||
763 | fn coercion_target(&self) -> Ty { | 750 | fn coercion_target(&self) -> Ty { |
764 | if self.rvalue_hint { | 751 | if self.rvalue_hint { |
765 | // FIXME | 752 | // FIXME |
766 | TyKind::Unknown.intern(&Interner) | 753 | TyKind::Error.intern(&Interner) |
767 | } else { | 754 | } else { |
768 | self.ty.clone() | 755 | self.ty.clone() |
769 | } | 756 | } |