mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-03 05:27:36 +00:00
Make let statements kind of work
This commit is contained in:
parent
5d60937090
commit
93ffbf80c6
@ -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<Ty> {
|
||||
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<Ty> {
|
||||
// TODO implement coercion
|
||||
self.unify(ty1, ty2)
|
||||
}
|
||||
|
||||
fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option<Ty> {
|
||||
@ -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() {
|
||||
|
5
crates/ra_hir/src/ty/tests/data/0002_let.rs
Normal file
5
crates/ra_hir/src/ty/tests/data/0002_let.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn test() {
|
||||
let a = 1isize;
|
||||
let b: usize = 1;
|
||||
let c = b;
|
||||
}
|
7
crates/ra_hir/src/ty/tests/data/0002_let.txt
Normal file
7
crates/ra_hir/src/ty/tests/data/0002_let.txt
Normal file
@ -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
|
@ -1561,6 +1561,10 @@ impl<'a> LetStmt<'a> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
|
||||
pub fn type_ref(self) -> Option<TypeRef<'a>> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
|
||||
pub fn initializer(self) -> Option<Expr<'a>> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
|
@ -499,6 +499,7 @@ Grammar(
|
||||
),
|
||||
"LetStmt": ( options: [
|
||||
["pat", "Pat"],
|
||||
["type_ref", "TypeRef"],
|
||||
["initializer", "Expr"],
|
||||
]),
|
||||
"Condition": (
|
||||
|
Loading…
Reference in New Issue
Block a user