aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty.rs44
-rw-r--r--crates/ra_hir/src/ty/tests/data/0002_let.rs5
-rw-r--r--crates/ra_hir/src/ty/tests/data/0002_let.txt7
3 files changed, 48 insertions, 8 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index eb5fea153..615a1caed 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -243,8 +243,23 @@ impl InferenceContext {
243 self.type_for.insert(LocalSyntaxPtr::new(node), ty); 243 self.type_for.insert(LocalSyntaxPtr::new(node), ty);
244 } 244 }
245 245
246 fn unify(&mut self, _ty1: &Ty, _ty2: &Ty) -> bool { 246 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> Option<Ty> {
247 unimplemented!() 247 if *ty1 == Ty::Unknown {
248 return Some(ty2.clone());
249 }
250 if *ty2 == Ty::Unknown {
251 return Some(ty1.clone());
252 }
253 if ty1 == ty2 {
254 return Some(ty1.clone());
255 }
256 // TODO implement actual unification
257 return None;
258 }
259
260 fn unify_with_coercion(&mut self, ty1: &Ty, ty2: &Ty) -> Option<Ty> {
261 // TODO implement coercion
262 self.unify(ty1, ty2)
248 } 263 }
249 264
250 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option<Ty> { 265 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option<Ty> {
@@ -280,9 +295,8 @@ impl InferenceContext {
280 } else { 295 } else {
281 Ty::Unknown 296 Ty::Unknown
282 }; 297 };
283 if self.unify(&if_ty, &else_ty) { 298 if let Some(ty) = self.unify(&if_ty, &else_ty) {
284 // TODO actually, need to take the 'more specific' type (not unknown, never, ...) 299 ty
285 if_ty
286 } else { 300 } else {
287 // TODO report diagnostic 301 // TODO report diagnostic
288 Ty::Unknown 302 Ty::Unknown
@@ -455,9 +469,23 @@ impl InferenceContext {
455 for stmt in node.statements() { 469 for stmt in node.statements() {
456 match stmt { 470 match stmt {
457 ast::Stmt::LetStmt(stmt) => { 471 ast::Stmt::LetStmt(stmt) => {
458 if let Some(expr) = stmt.initializer() { 472 let decl_ty = if let Some(type_ref) = stmt.type_ref() {
459 self.infer_expr(expr); 473 Ty::new(type_ref)
460 } 474 } else {
475 Ty::Unknown
476 };
477 let ty = if let Some(expr) = stmt.initializer() {
478 // TODO pass expectation
479 let expr_ty = self.infer_expr(expr);
480 self.unify_with_coercion(&expr_ty, &decl_ty)
481 .unwrap_or(decl_ty)
482 } else {
483 decl_ty
484 };
485
486 if let Some(pat) = stmt.pat() {
487 self.write_ty(pat.syntax(), ty);
488 };
461 } 489 }
462 ast::Stmt::ExprStmt(expr_stmt) => { 490 ast::Stmt::ExprStmt(expr_stmt) => {
463 if let Some(expr) = expr_stmt.expr() { 491 if let Some(expr) = expr_stmt.expr() {
diff --git a/crates/ra_hir/src/ty/tests/data/0002_let.rs b/crates/ra_hir/src/ty/tests/data/0002_let.rs
new file mode 100644
index 000000000..5641da75b
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/0002_let.rs
@@ -0,0 +1,5 @@
1fn test() {
2 let a = 1isize;
3 let b: usize = 1;
4 let c = b;
5}
diff --git a/crates/ra_hir/src/ty/tests/data/0002_let.txt b/crates/ra_hir/src/ty/tests/data/0002_let.txt
new file mode 100644
index 000000000..5f515ee59
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/0002_let.txt
@@ -0,0 +1,7 @@
1[51; 52) '1': [unknown]
2[10; 70) '{ ...= b; }': ()
3[24; 30) '1isize': [unknown]
4[20; 21) 'a': [unknown]
5[62; 63) 'c': usize
6[66; 67) 'b': usize
7[40; 41) 'b': usize