From 93ffbf80c632a7d38fc8bbdf6357bfd26a96a35a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 23 Dec 2018 13:22:29 +0100 Subject: Make let statements kind of work --- crates/ra_hir/src/ty.rs | 44 +++++++++++++++++++++++----- crates/ra_hir/src/ty/tests/data/0002_let.rs | 5 ++++ crates/ra_hir/src/ty/tests/data/0002_let.txt | 7 +++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 crates/ra_hir/src/ty/tests/data/0002_let.rs create mode 100644 crates/ra_hir/src/ty/tests/data/0002_let.txt (limited to 'crates/ra_hir') 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 { self.type_for.insert(LocalSyntaxPtr::new(node), ty); } - fn unify(&mut self, _ty1: &Ty, _ty2: &Ty) -> bool { - unimplemented!() + fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> Option { + if *ty1 == Ty::Unknown { + return Some(ty2.clone()); + } + if *ty2 == Ty::Unknown { + return Some(ty1.clone()); + } + if ty1 == ty2 { + return Some(ty1.clone()); + } + // TODO implement actual unification + return None; + } + + fn unify_with_coercion(&mut self, ty1: &Ty, ty2: &Ty) -> Option { + // TODO implement coercion + self.unify(ty1, ty2) } fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option { @@ -280,9 +295,8 @@ impl InferenceContext { } else { Ty::Unknown }; - if self.unify(&if_ty, &else_ty) { - // TODO actually, need to take the 'more specific' type (not unknown, never, ...) - if_ty + if let Some(ty) = self.unify(&if_ty, &else_ty) { + ty } else { // TODO report diagnostic Ty::Unknown @@ -455,9 +469,23 @@ impl InferenceContext { for stmt in node.statements() { match stmt { ast::Stmt::LetStmt(stmt) => { - if let Some(expr) = stmt.initializer() { - self.infer_expr(expr); - } + let decl_ty = if let Some(type_ref) = stmt.type_ref() { + Ty::new(type_ref) + } else { + Ty::Unknown + }; + let ty = if let Some(expr) = stmt.initializer() { + // TODO pass expectation + let expr_ty = self.infer_expr(expr); + self.unify_with_coercion(&expr_ty, &decl_ty) + .unwrap_or(decl_ty) + } else { + decl_ty + }; + + if let Some(pat) = stmt.pat() { + self.write_ty(pat.syntax(), ty); + }; } ast::Stmt::ExprStmt(expr_stmt) => { 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 @@ +fn test() { + let a = 1isize; + let b: usize = 1; + let c = b; +} 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 @@ +[51; 52) '1': [unknown] +[10; 70) '{ ...= b; }': () +[24; 30) '1isize': [unknown] +[20; 21) 'a': [unknown] +[62; 63) 'c': usize +[66; 67) 'b': usize +[40; 41) 'b': usize -- cgit v1.2.3