diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 189 |
1 files changed, 99 insertions, 90 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 3dec5936a..b28bb47c6 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -461,6 +461,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
461 | for segment in &path.segments[remaining_index..] { | 461 | for segment in &path.segments[remaining_index..] { |
462 | let ty = match resolved { | 462 | let ty = match resolved { |
463 | Resolution::Def(def) => { | 463 | Resolution::Def(def) => { |
464 | // FIXME resolve associated items from traits as well | ||
464 | let typable: Option<TypableDef> = def.into(); | 465 | let typable: Option<TypableDef> = def.into(); |
465 | let typable = typable?; | 466 | let typable = typable?; |
466 | 467 | ||
@@ -750,12 +751,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
750 | fn substs_for_method_call( | 751 | fn substs_for_method_call( |
751 | &mut self, | 752 | &mut self, |
752 | def_generics: Option<Arc<GenericParams>>, | 753 | def_generics: Option<Arc<GenericParams>>, |
753 | generic_args: &Option<GenericArgs>, | 754 | generic_args: Option<&GenericArgs>, |
754 | receiver_ty: &Ty, | 755 | receiver_ty: &Ty, |
755 | ) -> Substs { | 756 | ) -> Substs { |
756 | let (parent_param_count, param_count) = | 757 | let (parent_param_count, param_count) = |
757 | def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | 758 | def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); |
758 | let mut substs = Vec::with_capacity(parent_param_count + param_count); | 759 | let mut substs = Vec::with_capacity(parent_param_count + param_count); |
760 | // Parent arguments are unknown, except for the receiver type | ||
759 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { | 761 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { |
760 | for param in &parent_generics.params { | 762 | for param in &parent_generics.params { |
761 | if param.name.as_known_name() == Some(crate::KnownName::SelfType) { | 763 | if param.name.as_known_name() == Some(crate::KnownName::SelfType) { |
@@ -785,6 +787,100 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
785 | Substs(substs.into()) | 787 | Substs(substs.into()) |
786 | } | 788 | } |
787 | 789 | ||
790 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | ||
791 | match callable_ty { | ||
792 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
793 | TypeCtor::FnDef(def) => { | ||
794 | // add obligation for trait implementation, if this is a trait method | ||
795 | // FIXME also register obligations from where clauses from the trait or impl and method | ||
796 | match def { | ||
797 | CallableDef::Function(f) => { | ||
798 | if let Some(trait_) = f.parent_trait(self.db) { | ||
799 | // construct a TraitDef | ||
800 | let substs = a_ty.parameters.prefix( | ||
801 | trait_.generic_params(self.db).count_params_including_parent(), | ||
802 | ); | ||
803 | self.obligations | ||
804 | .push(Obligation::Trait(TraitRef { trait_, substs })); | ||
805 | } | ||
806 | } | ||
807 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {} | ||
808 | } | ||
809 | } | ||
810 | _ => {} | ||
811 | }, | ||
812 | _ => {} | ||
813 | } | ||
814 | } | ||
815 | |||
816 | fn infer_method_call( | ||
817 | &mut self, | ||
818 | tgt_expr: ExprId, | ||
819 | receiver: ExprId, | ||
820 | args: &[ExprId], | ||
821 | method_name: &Name, | ||
822 | generic_args: Option<&GenericArgs>, | ||
823 | ) -> Ty { | ||
824 | let receiver_ty = self.infer_expr(receiver, &Expectation::none()); | ||
825 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver); | ||
826 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | ||
827 | Some((ty, func)) => { | ||
828 | self.write_method_resolution(tgt_expr, func); | ||
829 | ( | ||
830 | ty, | ||
831 | self.db.type_for_def(func.into(), Namespace::Values), | ||
832 | Some(func.generic_params(self.db)), | ||
833 | ) | ||
834 | } | ||
835 | None => (receiver_ty, Ty::Unknown, None), | ||
836 | }; | ||
837 | let substs = | ||
838 | self.substs_for_method_call(def_generics.clone(), generic_args, &derefed_receiver_ty); | ||
839 | let method_ty = method_ty.apply_substs(substs); | ||
840 | let method_ty = self.insert_type_vars(method_ty); | ||
841 | self.register_obligations_for_call(&method_ty); | ||
842 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | ||
843 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
844 | TypeCtor::FnPtr => { | ||
845 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); | ||
846 | if !sig.params().is_empty() { | ||
847 | (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) | ||
848 | } else { | ||
849 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | ||
850 | } | ||
851 | } | ||
852 | TypeCtor::FnDef(def) => { | ||
853 | let sig = self.db.callable_item_signature(def); | ||
854 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); | ||
855 | |||
856 | if !sig.params().is_empty() { | ||
857 | let mut params_iter = | ||
858 | sig.params().iter().map(|ty| ty.clone().subst(&a_ty.parameters)); | ||
859 | let receiver_ty = params_iter.next().unwrap(); | ||
860 | (receiver_ty, params_iter.collect(), ret_ty) | ||
861 | } else { | ||
862 | (Ty::Unknown, Vec::new(), ret_ty) | ||
863 | } | ||
864 | } | ||
865 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
866 | }, | ||
867 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
868 | }; | ||
869 | // Apply autoref so the below unification works correctly | ||
870 | // FIXME: return correct autorefs from lookup_method | ||
871 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | ||
872 | Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), | ||
873 | _ => derefed_receiver_ty, | ||
874 | }; | ||
875 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
876 | |||
877 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
878 | for (arg, param) in args.iter().zip(param_iter) { | ||
879 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
880 | } | ||
881 | ret_ty | ||
882 | } | ||
883 | |||
788 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 884 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
789 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 885 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
790 | let ty = match &body[tgt_expr] { | 886 | let ty = match &body[tgt_expr] { |
@@ -872,95 +968,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
872 | } | 968 | } |
873 | ret_ty | 969 | ret_ty |
874 | } | 970 | } |
875 | Expr::MethodCall { receiver, args, method_name, generic_args } => { | 971 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
876 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 972 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
877 | let resolved = | ||
878 | receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver); | ||
879 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | ||
880 | Some((ty, func)) => { | ||
881 | self.write_method_resolution(tgt_expr, func); | ||
882 | ( | ||
883 | ty, | ||
884 | self.db.type_for_def(func.into(), Namespace::Values), | ||
885 | Some(func.generic_params(self.db)), | ||
886 | ) | ||
887 | } | ||
888 | None => (receiver_ty, Ty::Unknown, None), | ||
889 | }; | ||
890 | let substs = self.substs_for_method_call( | ||
891 | def_generics.clone(), | ||
892 | generic_args, | ||
893 | &derefed_receiver_ty, | ||
894 | ); | ||
895 | let method_ty = method_ty.apply_substs(substs); | ||
896 | let method_ty = self.insert_type_vars(method_ty); | ||
897 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | ||
898 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
899 | TypeCtor::FnPtr => { | ||
900 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); | ||
901 | if !sig.params().is_empty() { | ||
902 | ( | ||
903 | sig.params()[0].clone(), | ||
904 | sig.params()[1..].to_vec(), | ||
905 | sig.ret().clone(), | ||
906 | ) | ||
907 | } else { | ||
908 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | ||
909 | } | ||
910 | } | ||
911 | TypeCtor::FnDef(def) => { | ||
912 | let sig = self.db.callable_item_signature(def); | ||
913 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); | ||
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 | |||
933 | if !sig.params().is_empty() { | ||
934 | let mut params_iter = sig | ||
935 | .params() | ||
936 | .iter() | ||
937 | .map(|ty| ty.clone().subst(&a_ty.parameters)); | ||
938 | let receiver_ty = params_iter.next().unwrap(); | ||
939 | (receiver_ty, params_iter.collect(), ret_ty) | ||
940 | } else { | ||
941 | (Ty::Unknown, Vec::new(), ret_ty) | ||
942 | } | ||
943 | } | ||
944 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
945 | }, | ||
946 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
947 | }; | ||
948 | // Apply autoref so the below unification works correctly | ||
949 | // FIXME: return correct autorefs/derefs from lookup_method | ||
950 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | ||
951 | Some((_, mutability)) => { | ||
952 | Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) | ||
953 | } | ||
954 | _ => derefed_receiver_ty, | ||
955 | }; | ||
956 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
957 | |||
958 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
959 | for (arg, param) in args.iter().zip(param_iter) { | ||
960 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
961 | } | ||
962 | ret_ty | ||
963 | } | ||
964 | Expr::Match { expr, arms } => { | 973 | Expr::Match { expr, arms } => { |
965 | let expected = if expected.ty == Ty::Unknown { | 974 | let expected = if expected.ty == Ty::Unknown { |
966 | Expectation::has_type(self.new_type_var()) | 975 | Expectation::has_type(self.new_type_var()) |