diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 84 |
1 files changed, 78 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 28947be51..3dec5936a 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -41,7 +41,7 @@ use crate::{ | |||
41 | ty::infer::diagnostics::InferenceDiagnostic, | 41 | ty::infer::diagnostics::InferenceDiagnostic, |
42 | diagnostics::DiagnosticSink, | 42 | diagnostics::DiagnosticSink, |
43 | }; | 43 | }; |
44 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 44 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor, traits::{ Solution, Obligation, Guidance}, CallableDef, TraitRef}; |
45 | 45 | ||
46 | /// The entry point of type inference. | 46 | /// The entry point of type inference. |
47 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { | 47 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { |
@@ -153,6 +153,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
153 | body: Arc<Body>, | 153 | body: Arc<Body>, |
154 | resolver: Resolver, | 154 | resolver: Resolver, |
155 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 155 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
156 | obligations: Vec<Obligation>, | ||
156 | method_resolutions: FxHashMap<ExprId, Function>, | 157 | method_resolutions: FxHashMap<ExprId, Function>, |
157 | field_resolutions: FxHashMap<ExprId, StructField>, | 158 | field_resolutions: FxHashMap<ExprId, StructField>, |
158 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, | 159 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, |
@@ -173,6 +174,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
173 | type_of_pat: ArenaMap::default(), | 174 | type_of_pat: ArenaMap::default(), |
174 | diagnostics: Vec::default(), | 175 | diagnostics: Vec::default(), |
175 | var_unification_table: InPlaceUnificationTable::new(), | 176 | var_unification_table: InPlaceUnificationTable::new(), |
177 | obligations: Vec::default(), | ||
176 | return_ty: Ty::Unknown, // set in collect_fn_signature | 178 | return_ty: Ty::Unknown, // set in collect_fn_signature |
177 | db, | 179 | db, |
178 | body, | 180 | body, |
@@ -181,6 +183,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
181 | } | 183 | } |
182 | 184 | ||
183 | fn resolve_all(mut self) -> InferenceResult { | 185 | fn resolve_all(mut self) -> InferenceResult { |
186 | // FIXME resolve obligations as well (use Guidance if necessary) | ||
184 | let mut tv_stack = Vec::new(); | 187 | let mut tv_stack = Vec::new(); |
185 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); | 188 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); |
186 | for ty in expr_types.values_mut() { | 189 | for ty in expr_types.values_mut() { |
@@ -311,11 +314,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
311 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | 314 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) |
312 | } | 315 | } |
313 | 316 | ||
317 | fn resolve_obligations_as_possible(&mut self) { | ||
318 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | ||
319 | for obligation in obligations { | ||
320 | // FIXME resolve types in the obligation first | ||
321 | let (solution, var_mapping) = match &obligation { | ||
322 | Obligation::Trait(tr) => { | ||
323 | let (tr, var_mapping) = super::traits::canonicalize(tr.clone()); | ||
324 | (self.db.implements(tr), var_mapping) | ||
325 | } | ||
326 | }; | ||
327 | match solution { | ||
328 | Some(Solution::Unique(substs)) => { | ||
329 | for (i, subst) in substs.0.iter().enumerate() { | ||
330 | let uncanonical = var_mapping[i]; | ||
331 | // FIXME the subst may contain type variables, which would need to be mapped back as well | ||
332 | self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst); | ||
333 | } | ||
334 | } | ||
335 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
336 | for (i, subst) in substs.0.iter().enumerate() { | ||
337 | let uncanonical = var_mapping[i]; | ||
338 | // FIXME the subst may contain type variables, which would need to be mapped back as well | ||
339 | self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst); | ||
340 | } | ||
341 | self.obligations.push(obligation); | ||
342 | } | ||
343 | Some(_) => { | ||
344 | self.obligations.push(obligation); | ||
345 | } | ||
346 | None => { | ||
347 | // FIXME obligation cannot be fulfilled => diagnostic | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
314 | /// Resolves the type as far as currently possible, replacing type variables | 353 | /// Resolves the type as far as currently possible, replacing type variables |
315 | /// by their known types. All types returned by the infer_* functions should | 354 | /// by their known types. All types returned by the infer_* functions should |
316 | /// be resolved as far as possible, i.e. contain no type variables with | 355 | /// be resolved as far as possible, i.e. contain no type variables with |
317 | /// known type. | 356 | /// known type. |
318 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 357 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
358 | self.resolve_obligations_as_possible(); | ||
359 | |||
319 | ty.fold(&mut |ty| match ty { | 360 | ty.fold(&mut |ty| match ty { |
320 | Ty::Infer(tv) => { | 361 | Ty::Infer(tv) => { |
321 | let inner = tv.to_inner(); | 362 | let inner = tv.to_inner(); |
@@ -710,12 +751,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
710 | &mut self, | 751 | &mut self, |
711 | def_generics: Option<Arc<GenericParams>>, | 752 | def_generics: Option<Arc<GenericParams>>, |
712 | generic_args: &Option<GenericArgs>, | 753 | generic_args: &Option<GenericArgs>, |
754 | receiver_ty: &Ty, | ||
713 | ) -> Substs { | 755 | ) -> Substs { |
714 | let (parent_param_count, param_count) = | 756 | let (parent_param_count, param_count) = |
715 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | 757 | def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); |
716 | let mut substs = Vec::with_capacity(parent_param_count + param_count); | 758 | let mut substs = Vec::with_capacity(parent_param_count + param_count); |
717 | for _ in 0..parent_param_count { | 759 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { |
718 | substs.push(Ty::Unknown); | 760 | for param in &parent_generics.params { |
761 | if param.name.as_known_name() == Some(crate::KnownName::SelfType) { | ||
762 | substs.push(receiver_ty.clone()); | ||
763 | } else { | ||
764 | substs.push(Ty::Unknown); | ||
765 | } | ||
766 | } | ||
719 | } | 767 | } |
720 | // handle provided type arguments | 768 | // handle provided type arguments |
721 | if let Some(generic_args) = generic_args { | 769 | if let Some(generic_args) = generic_args { |
@@ -817,6 +865,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
817 | (Vec::new(), Ty::Unknown) | 865 | (Vec::new(), Ty::Unknown) |
818 | } | 866 | } |
819 | }; | 867 | }; |
868 | // FIXME register obligations from where clauses from the function | ||
820 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 869 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
821 | for (arg, param) in args.iter().zip(param_iter) { | 870 | for (arg, param) in args.iter().zip(param_iter) { |
822 | self.infer_expr(*arg, &Expectation::has_type(param)); | 871 | self.infer_expr(*arg, &Expectation::has_type(param)); |
@@ -838,7 +887,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
838 | } | 887 | } |
839 | None => (receiver_ty, Ty::Unknown, None), | 888 | None => (receiver_ty, Ty::Unknown, None), |
840 | }; | 889 | }; |
841 | let substs = self.substs_for_method_call(def_generics, generic_args); | 890 | let substs = self.substs_for_method_call( |
891 | def_generics.clone(), | ||
892 | generic_args, | ||
893 | &derefed_receiver_ty, | ||
894 | ); | ||
842 | let method_ty = method_ty.apply_substs(substs); | 895 | let method_ty = method_ty.apply_substs(substs); |
843 | let method_ty = self.insert_type_vars(method_ty); | 896 | let method_ty = self.insert_type_vars(method_ty); |
844 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 897 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
@@ -859,6 +912,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
859 | let sig = self.db.callable_item_signature(def); | 912 | let sig = self.db.callable_item_signature(def); |
860 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); | 913 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); |
861 | 914 | ||
915 | // add obligation for trait implementation, if this is a trait method | ||
916 | // FIXME also register obligations from where clauses from the trait or impl and method | ||
917 | match def { | ||
918 | CallableDef::Function(f) => { | ||
919 | if let Some(trait_) = f.parent_trait(self.db) { | ||
920 | // construct a TraitDef | ||
921 | let substs = a_ty.parameters.prefix( | ||
922 | def_generics | ||
923 | .expect("trait parent should always have generics") | ||
924 | .count_parent_params(), | ||
925 | ); | ||
926 | self.obligations | ||
927 | .push(Obligation::Trait(TraitRef { trait_, substs })); | ||
928 | } | ||
929 | } | ||
930 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {} | ||
931 | } | ||
932 | |||
862 | if !sig.params().is_empty() { | 933 | if !sig.params().is_empty() { |
863 | let mut params_iter = sig | 934 | let mut params_iter = sig |
864 | .params() | 935 | .params() |
@@ -875,6 +946,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
875 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | 946 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), |
876 | }; | 947 | }; |
877 | // Apply autoref so the below unification works correctly | 948 | // Apply autoref so the below unification works correctly |
949 | // FIXME: return correct autorefs/derefs from lookup_method | ||
878 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | 950 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { |
879 | Some((_, mutability)) => { | 951 | Some((_, mutability)) => { |
880 | Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) | 952 | Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) |
@@ -1180,7 +1252,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1180 | 1252 | ||
1181 | /// The ID of a type variable. | 1253 | /// The ID of a type variable. |
1182 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 1254 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
1183 | pub struct TypeVarId(u32); | 1255 | pub struct TypeVarId(pub(super) u32); |
1184 | 1256 | ||
1185 | impl UnifyKey for TypeVarId { | 1257 | impl UnifyKey for TypeVarId { |
1186 | type Value = TypeVarValue; | 1258 | type Value = TypeVarValue; |