aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-23 12:22:29 +0000
committerFlorian Diebold <[email protected]>2018-12-23 13:01:50 +0000
commit93ffbf80c632a7d38fc8bbdf6357bfd26a96a35a (patch)
tree59c9f26c70ffa45f599b711cd2b6233e865ccd8b
parent5d609370900402db84beb3d7e28487256c6042c2 (diff)
Make let statements kind of work
-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
-rw-r--r--crates/ra_syntax/src/ast/generated.rs4
-rw-r--r--crates/ra_syntax/src/grammar.ron1
5 files changed, 53 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
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 74bf4d3cc..b15c4ef6f 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1561,6 +1561,10 @@ impl<'a> LetStmt<'a> {
1561 super::child_opt(self) 1561 super::child_opt(self)
1562 } 1562 }
1563 1563
1564 pub fn type_ref(self) -> Option<TypeRef<'a>> {
1565 super::child_opt(self)
1566 }
1567
1564 pub fn initializer(self) -> Option<Expr<'a>> { 1568 pub fn initializer(self) -> Option<Expr<'a>> {
1565 super::child_opt(self) 1569 super::child_opt(self)
1566 } 1570 }
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 29b84854a..8dca493ee 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -499,6 +499,7 @@ Grammar(
499 ), 499 ),
500 "LetStmt": ( options: [ 500 "LetStmt": ( options: [
501 ["pat", "Pat"], 501 ["pat", "Pat"],
502 ["type_ref", "TypeRef"],
502 ["initializer", "Expr"], 503 ["initializer", "Expr"],
503 ]), 504 ]),
504 "Condition": ( 505 "Condition": (