diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 00c51a2a3c..991d3c4b8d 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -13,6 +13,24 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { node.left_type = left_type c.expected_type = left_type + // `if n is ast.Ident && n.is_mut { ... }` + if node.op == .and { + mut left_node := node.left + for mut left_node is ast.InfixExpr { + if left_node.op == .key_is { + // search `n is ast.Ident` + from_type := c.expr(left_node.left) + to_type := c.expr(left_node.right) + c.autocast_in_if_conds(mut node.right, left_node.left, from_type, to_type) + break + } else if left_node.op == .and { + left_node = left_node.left + } else { + break + } + } + } + if node.op == .key_is { c.inside_x_is_type = true } @@ -793,3 +811,25 @@ fn (mut c Checker) invalid_operator_error(op token.Kind, left_type ast.Type, rig right_name := c.table.type_to_str(right_type) c.error('invalid operator `${op}` to `${left_name}` and `${right_name}`', pos) } + +// `if node is ast.Ident && node.is_mut { ... }` -> `if node is ast.Ident && (node as ast.Ident).is_mut { ... }` +fn (mut c Checker) autocast_in_if_conds(mut right ast.Expr, from_expr ast.Expr, from_type ast.Type, to_type ast.Type) { + match mut right { + ast.SelectorExpr { + if right.expr.str() == from_expr.str() { + right.expr = ast.ParExpr{ + expr: ast.AsCast{ + typ: to_type + expr: from_expr + expr_type: from_type + } + } + } + } + ast.InfixExpr { + c.autocast_in_if_conds(mut right.left, from_expr, from_type, to_type) + c.autocast_in_if_conds(mut right.right, from_expr, from_type, to_type) + } + else {} + } +} diff --git a/vlib/v/tests/autocast_in_if_conds_test.v b/vlib/v/tests/autocast_in_if_conds_test.v new file mode 100644 index 0000000000..5a06cdcef2 --- /dev/null +++ b/vlib/v/tests/autocast_in_if_conds_test.v @@ -0,0 +1,24 @@ +type MySumType = S1 | S2 + +struct S1 { + is_name bool + name string +} + +struct S2 { + field2 bool +} + +fn test_autocast_in_if_conds() { + s := MySumType(S1{ + is_name: true + name: 'bob' + }) + + if s is S1 && s.is_name && s.name == 'bob' { + println('ok') + assert true + } else { + assert false + } +}