aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-04-09 21:04:59 +0100
committerFlorian Diebold <[email protected]>2019-04-14 10:28:53 +0100
commit9339241b78ef7474e88de37738bdbece7767d333 (patch)
treec253d26db406b0f6cac5db67a054f4334b016486
parenta1ed53a4f183b5826162eb9e998207b92be9c57f (diff)
Some cleanup
-rw-r--r--crates/ra_hir/src/ty/infer.rs189
-rw-r--r--crates/ra_hir/src/ty/lower.rs7
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs13
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.
8use std::iter;
8 9
9use crate::{ 10use 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.
236fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs { 240fn 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}