aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-03-31 19:02:16 +0100
committerFlorian Diebold <[email protected]>2019-04-14 10:28:53 +0100
commita1ed53a4f183b5826162eb9e998207b92be9c57f (patch)
tree7c139a7dc38483188653c6d40583cddac9d23192 /crates/ra_hir/src/ty/infer.rs
parent413c87f155ab6b389b1cc122b5739716acccb476 (diff)
More trait infrastructure
- make it possible to get parent trait from method - add 'obligation' machinery for checking that a type implements a trait (and inferring facts about type variables from that) - handle type parameters of traits (to a certain degree) - improve the hacky implements check to cover enough cases to exercise the handling of traits with type parameters - basic canonicalization (will probably also be done by Chalk)
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs84
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};
44use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; 44use 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.
47pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 47pub 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)]
1183pub struct TypeVarId(u32); 1255pub struct TypeVarId(pub(super) u32);
1184 1256
1185impl UnifyKey for TypeVarId { 1257impl UnifyKey for TypeVarId {
1186 type Value = TypeVarValue; 1258 type Value = TypeVarValue;