checker: implement smartcast if multi conds (part 1/2) (#10452)

pull/10457/head
yuyi 2021-06-14 23:10:29 +08:00 committed by GitHub
parent 694b991929
commit e5debbbe01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 47 additions and 0 deletions

View File

@ -5863,6 +5863,53 @@ pub fn (mut c Checker) unsafe_expr(mut node ast.UnsafeExpr) ast.Type {
return t return t
} }
fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
if node is ast.InfixExpr {
if node.op == .and {
c.smartcast_if_conds(node.left, mut scope)
c.smartcast_if_conds(node.right, mut scope)
} else if node.op == .key_is {
right_expr := node.right
right_type := match right_expr {
ast.TypeNode {
right_expr.typ
}
ast.None {
ast.none_type_idx
}
else {
c.error('invalid type `$right_expr`', right_expr.position())
ast.Type(0)
}
}
if right_type != ast.Type(0) {
left_sym := c.table.get_type_symbol(node.left_type)
expr_type := c.expr(node.left)
if left_sym.kind == .interface_ {
c.type_implements(right_type, expr_type, node.pos)
} else if !c.check_types(right_type, expr_type) {
expect_str := c.table.type_to_str(right_type)
expr_str := c.table.type_to_str(expr_type)
c.error('cannot use type `$expect_str` as type `$expr_str`', node.pos)
}
if (node.left is ast.Ident || node.left is ast.SelectorExpr)
&& node.right is ast.TypeNode {
is_variable := if mut node.left is ast.Ident {
node.left.kind == .variable
} else {
true
}
if is_variable {
if left_sym.kind in [.interface_, .sum_type] {
c.smartcast(node.left, node.left_type, right_type, mut scope)
}
}
}
}
}
}
}
pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
if_kind := if node.is_comptime { '\$if' } else { 'if' } if_kind := if node.is_comptime { '\$if' } else { 'if' }
mut node_is_expr := false mut node_is_expr := false