aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-15 17:47:37 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:25 +0000
commit5648dcd36e65dde9c8f41884eed64a7e1a1d2073 (patch)
tree677c70225c3651ba65fa439782bda8d78dc029c7
parentafaa26636e4391ebacfc09e9c994c11bab58b834 (diff)
Implement type inference for tuples and refs
-rw-r--r--crates/ra_hir/src/ty.rs39
-rw-r--r--crates/ra_hir/src/ty/tests.rs11
-rw-r--r--crates/ra_hir/src/ty/tests/data/pattern.txt15
3 files changed, 58 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 854d3e3d9..324df5ef9 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -36,7 +36,7 @@ use crate::{
36 db::HirDatabase, 36 db::HirDatabase,
37 type_ref::{TypeRef, Mutability}, 37 type_ref::{TypeRef, Mutability},
38 name::KnownName, 38 name::KnownName,
39 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement}, 39 expr::{Body, Expr, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement},
40}; 40};
41 41
42/// The ID of a type variable. 42/// The ID of a type variable.
@@ -872,6 +872,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
872 } 872 }
873 } 873 }
874 874
875 // FIXME: Expectation should probably contain a reference to a Ty instead of
876 // a Ty itself
877 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
878 let body = Arc::clone(&self.body); // avoid borrow checker problem
879 match (&body[pat], &expected.ty) {
880 (Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
881 if args.len() == tuple_args.len() =>
882 {
883 for (&pat, ty) in args.iter().zip(tuple_args.iter()) {
884 // FIXME: can we do w/o cloning?
885 self.infer_pat(pat, &Expectation::has_type(ty.clone()));
886 }
887 }
888 (&Pat::Ref { pat, mutability }, &Ty::Ref(ref sub_ty, ty_mut))
889 if mutability == ty_mut =>
890 {
891 self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone()));
892 }
893 // TODO: implement more
894 (_, ref _expected_ty) => {}
895 };
896 // use a new type variable if we got Ty::Unknown here
897 let ty = self.insert_type_vars_shallow(expected.ty.clone());
898 self.unify(&ty, &expected.ty);
899 let ty = self.resolve_ty_as_possible(ty);
900 self.write_pat_ty(pat, ty.clone());
901 ty
902 }
903
875 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 904 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
876 let body = Arc::clone(&self.body); // avoid borrow checker problem 905 let body = Arc::clone(&self.body); // avoid borrow checker problem
877 let ty = match &body[expr] { 906 let ty = match &body[expr] {
@@ -1168,9 +1197,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1168 decl_ty 1197 decl_ty
1169 }; 1198 };
1170 1199
1171 // TODO: walk the pattern here? 1200 self.infer_pat(*pat, &Expectation::has_type(ty))?;
1172
1173 self.write_pat_ty(*pat, ty);
1174 } 1201 }
1175 Statement::Expr(expr) => { 1202 Statement::Expr(expr) => {
1176 self.infer_expr(*expr, &Expectation::none()); 1203 self.infer_expr(*expr, &Expectation::none());
@@ -1191,9 +1218,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1191 let ty = self.make_ty(type_ref); 1218 let ty = self.make_ty(type_ref);
1192 let ty = self.insert_type_vars(ty); 1219 let ty = self.insert_type_vars(ty);
1193 1220
1194 // TODO: walk pattern? 1221 self.infer_pat(*pat, &Expectation::has_type(ty))?;
1195
1196 self.write_pat_ty(*pat, ty);
1197 } 1222 }
1198 self.return_ty = { 1223 self.return_ty = {
1199 let ty = self.make_ty(signature.ret_type()); 1224 let ty = self.make_ty(signature.ret_type());
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index fc1e5b09c..a55551cbb 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -362,11 +362,22 @@ fn test(x: &str, y: isize) {
362fn infer_pattern() { 362fn infer_pattern() {
363 check_inference( 363 check_inference(
364 r#" 364 r#"
365enum E { A { x: usize }, B }
366
365fn test(x: &i32) { 367fn test(x: &i32) {
366 let y = x; 368 let y = x;
367 let &z = x; 369 let &z = x;
368 let a = z; 370 let a = z;
369 let (c, d) = (1, "hello"); 371 let (c, d) = (1, "hello");
372
373 let e = E::A { x: 3 };
374 if let E::A { x: x } = e {
375 x
376 };
377 match e {
378 E::A { x } => x,
379 E::B => 1,
380 };
370} 381}
371"#, 382"#,
372 "pattern.txt", 383 "pattern.txt",
diff --git a/crates/ra_hir/src/ty/tests/data/pattern.txt b/crates/ra_hir/src/ty/tests/data/pattern.txt
new file mode 100644
index 000000000..cca521833
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/pattern.txt
@@ -0,0 +1,15 @@
1[9; 10) 'x': &i32
2[18; 98) '{ ...o"); }': ()
3[28; 29) 'y': &i32
4[32; 33) 'x': &i32
5[43; 45) '&z': &i32
6[44; 45) 'z': i32
7[48; 49) 'x': &i32
8[59; 60) 'a': i32
9[63; 64) 'z': i32
10[74; 80) '(c, d)': (i32, &str)
11[75; 76) 'c': i32
12[78; 79) 'd': &str
13[83; 95) '(1, "hello")': (i32, &str)
14[84; 85) '1': i32
15[87; 94) '"hello"': &str