aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-17 09:28:10 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:25 +0000
commitbe1b4034a523081cfeea1c7a1d61130d5d1778e1 (patch)
tree3fe6d410c51b01ebdc89260f9c241edf8c90bda3
parent06d16a18f632711de588ccd12a6a1ed6f2b9ad69 (diff)
Infer pattern types for lambdas and loops
-rw-r--r--crates/ra_hir/src/ty.rs44
-rw-r--r--crates/ra_hir/src/ty/tests.rs10
2 files changed, 39 insertions, 15 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 74996dda5..75794b732 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -33,6 +33,7 @@ use rustc_hash::FxHashMap;
33use crate::{ 33use crate::{
34 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock, 34 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock,
35 FnSignature, FnScopes, 35 FnSignature, FnScopes,
36 adt::StructField,
36 db::HirDatabase, 37 db::HirDatabase,
37 type_ref::{TypeRef, Mutability}, 38 type_ref::{TypeRef, Mutability},
38 name::KnownName, 39 name::KnownName,
@@ -872,7 +873,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
872 } 873 }
873 } 874 }
874 875
875 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<crate::adt::StructField>)> { 876 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
876 let def = path 877 let def = path
877 .and_then(|path| self.module.resolve_path(self.db, &path).take_types()) 878 .and_then(|path| self.module.resolve_path(self.db, &path).take_types())
878 .map(|def_id| def_id.resolve(self.db)); 879 .map(|def_id| def_id.resolve(self.db));
@@ -916,13 +917,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
916 } 917 }
917 918
918 for (&sub_pat, field) in sub_pats.iter().zip(fields.iter()) { 919 for (&sub_pat, field) in sub_pats.iter().zip(fields.iter()) {
919 let sub_ty = Ty::from_hir( 920 let sub_ty = self.make_ty(&field.type_ref);
920 self.db,
921 &self.module,
922 self.impl_block.as_ref(),
923 &field.type_ref,
924 );
925
926 self.infer_pat(sub_pat, &Expectation::has_type(sub_ty)); 921 self.infer_pat(sub_pat, &Expectation::has_type(sub_ty));
927 } 922 }
928 923
@@ -941,7 +936,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
941 936
942 if let Some(field) = matching_field { 937 if let Some(field) = matching_field {
943 let typeref = &field.type_ref; 938 let typeref = &field.type_ref;
944 let sub_ty = Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), typeref); 939 let sub_ty = self.make_ty(typeref);
945 self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty)); 940 self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty));
946 } 941 }
947 } 942 }
@@ -1031,14 +1026,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1031 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 1026 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
1032 Ty::unit() 1027 Ty::unit()
1033 } 1028 }
1034 Expr::For { iterable, body, .. } => { 1029 Expr::For {
1030 iterable,
1031 body,
1032 pat,
1033 } => {
1035 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 1034 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none());
1036 // TODO write type for pat 1035 self.infer_pat(*pat, &Expectation::none());
1037 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 1036 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
1038 Ty::unit() 1037 Ty::unit()
1039 } 1038 }
1040 Expr::Lambda { body, .. } => { 1039 Expr::Lambda {
1041 // TODO write types for args, infer lambda type etc. 1040 body,
1041 args,
1042 arg_types,
1043 } => {
1044 assert_eq!(args.len(), arg_types.len());
1045
1046 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
1047 let expected = if let Some(tyref) = arg_type {
1048 let ty = self.make_ty(tyref);
1049 Expectation::has_type(ty)
1050 } else {
1051 Expectation::none()
1052 };
1053 self.infer_pat(*arg_pat, &expected);
1054 }
1055
1056 // TODO: infer lambda type etc.
1042 let _body_ty = self.infer_expr(*body, &Expectation::none()); 1057 let _body_ty = self.infer_expr(*body, &Expectation::none());
1043 Ty::Unknown 1058 Ty::Unknown
1044 } 1059 }
@@ -1174,8 +1189,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1174 } 1189 }
1175 Expr::Cast { expr, type_ref } => { 1190 Expr::Cast { expr, type_ref } => {
1176 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 1191 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1177 let cast_ty = 1192 let cast_ty = self.make_ty(type_ref);
1178 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref);
1179 let cast_ty = self.insert_type_vars(cast_ty); 1193 let cast_ty = self.insert_type_vars(cast_ty);
1180 // TODO check the cast... 1194 // TODO check the cast...
1181 cast_ty 1195 cast_ty
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 10842f967..dfc83bb17 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -367,6 +367,16 @@ fn test(x: &i32) {
367 let &z = x; 367 let &z = x;
368 let a = z; 368 let a = z;
369 let (c, d) = (1, "hello"); 369 let (c, d) = (1, "hello");
370
371 for (e, f) in some_iter {
372 let g = e;
373 }
374
375 if let [val] = opt {
376 let h = val;
377 }
378
379 let lambda = |a: u64, b, c: i32| { a + b; c };
370} 380}
371"#, 381"#,
372 "pattern.txt", 382 "pattern.txt",