diff options
author | Florian Diebold <[email protected]> | 2019-04-09 21:04:59 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-04-14 10:28:53 +0100 |
commit | 9339241b78ef7474e88de37738bdbece7767d333 (patch) | |
tree | c253d26db406b0f6cac5db67a054f4334b016486 | |
parent | a1ed53a4f183b5826162eb9e998207b92be9c57f (diff) |
Some cleanup
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 189 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 13 |
3 files changed, 111 insertions, 98 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()) |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index ccacb5e73..bb8fdd8c7 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -5,6 +5,7 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::iter; | ||
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | Function, Struct, StructField, Enum, EnumVariant, Path, | 11 | Function, Struct, StructField, Enum, EnumVariant, Path, |
@@ -172,16 +173,18 @@ pub(super) fn substs_from_path_segment( | |||
172 | ) -> Substs { | 173 | ) -> Substs { |
173 | let mut substs = Vec::new(); | 174 | let mut substs = Vec::new(); |
174 | let parent_param_count = def_generics.count_parent_params(); | 175 | let parent_param_count = def_generics.count_parent_params(); |
175 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | 176 | substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); |
176 | if add_self_param { | 177 | if add_self_param { |
177 | // FIXME this add_self_param argument is kind of a hack: Traits have the | 178 | // FIXME this add_self_param argument is kind of a hack: Traits have the |
178 | // Self type as an implicit first type parameter, but it can't be | 179 | // Self type as an implicit first type parameter, but it can't be |
179 | // actually provided in the type arguments | 180 | // actually provided in the type arguments |
181 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
180 | substs.push(Ty::Unknown); | 182 | substs.push(Ty::Unknown); |
181 | } | 183 | } |
182 | if let Some(generic_args) = &segment.args_and_bindings { | 184 | if let Some(generic_args) = &segment.args_and_bindings { |
183 | // if args are provided, it should be all of them, but we can't rely on that | 185 | // if args are provided, it should be all of them, but we can't rely on that |
184 | let param_count = def_generics.params.len(); | 186 | let self_param_correction = if add_self_param { 1 } else { 0 }; |
187 | let param_count = def_generics.params.len() - self_param_correction; | ||
185 | for arg in generic_args.args.iter().take(param_count) { | 188 | for arg in generic_args.args.iter().take(param_count) { |
186 | match arg { | 189 | match arg { |
187 | GenericArg::Type(type_ref) => { | 190 | GenericArg::Type(type_ref) => { |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index f69b8304b..126edeaff 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -233,15 +233,16 @@ impl Ty { | |||
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | /// This creates Substs for a trait with the given Self type and type variables | ||
237 | /// for all other parameters. This is kind of a hack since these aren't 'real' | ||
238 | /// type variables; the resulting trait reference is just used for the | ||
239 | /// preliminary method candidate check. | ||
236 | fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs { | 240 | fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs { |
237 | let mut substs = Vec::new(); | 241 | let mut substs = Vec::new(); |
238 | let mut counter = 0; | ||
239 | let generics = tr.generic_params(db); | 242 | let generics = tr.generic_params(db); |
240 | substs.push(self_ty); | 243 | substs.push(self_ty); |
241 | substs.extend(generics.params_including_parent().into_iter().skip(1).map(|_p| { | 244 | substs.extend(generics.params_including_parent().into_iter().skip(1).enumerate().map( |
242 | let fresh_var = Ty::Infer(super::infer::InferTy::TypeVar(super::infer::TypeVarId(counter))); | 245 | |(i, _p)| Ty::Infer(super::infer::InferTy::TypeVar(super::infer::TypeVarId(i as u32))), |
243 | counter += 1; | 246 | )); |
244 | fresh_var | ||
245 | })); | ||
246 | substs.into() | 247 | substs.into() |
247 | } | 248 | } |