mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-07 09:13:07 +03:00
Make let statements kind of work
This commit is contained in:
+36
-8
@@ -243,8 +243,23 @@ fn write_ty(&mut self, node: SyntaxNodeRef, ty: Ty) {
|
||||
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 @@ fn infer_expr(&mut self, expr: ast::Expr) -> Ty {
|
||||
} 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 @@ fn infer_block(&mut self, node: ast::Block) -> Ty {
|
||||
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() {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
fn test() {
|
||||
let a = 1isize;
|
||||
let b: usize = 1;
|
||||
let c = b;
|
||||
}
|
||||
@@ -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 @@ pub fn pat(self) -> Option<Pat<'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": (
|
||||
|
||||
Reference in New Issue
Block a user