checker: implement if smartcast multi conds (part 1) (#10477)
parent
d56219a986
commit
1dca06495d
|
@ -4658,19 +4658,15 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
|||
c.ensure_type_exists(node.typ, node.pos) or {}
|
||||
if !c.table.sumtype_has_variant(node.expr_type, node.typ) {
|
||||
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
|
||||
// c.error('only $info.variants can be casted to `$typ`', node.pos)
|
||||
}
|
||||
} else {
|
||||
mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
|
||||
if type_sym.kind == .sum_type {
|
||||
s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
|
||||
}
|
||||
c.error(s, node.pos)
|
||||
// mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
|
||||
// if type_sym.kind == .sum_type {
|
||||
// s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
|
||||
// }
|
||||
// c.error(s, node.pos)
|
||||
}
|
||||
if expr_type_sym.kind == .sum_type {
|
||||
return node.typ
|
||||
}
|
||||
return node.typ.to_ptr()
|
||||
return node.typ
|
||||
}
|
||||
ast.Assoc {
|
||||
v := node.scope.find_var(node.var_name) or { panic(err) }
|
||||
|
@ -6038,50 +6034,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
c.skip_flags = cur_skip_flags
|
||||
} else {
|
||||
// smartcast sumtypes and interfaces when using `is`
|
||||
pos := branch.cond.position()
|
||||
if branch.cond is ast.InfixExpr {
|
||||
if branch.cond.op == .key_is {
|
||||
right_expr := branch.cond.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(branch.cond.left_type)
|
||||
expr_type := c.expr(branch.cond.left)
|
||||
if left_sym.kind == .interface_ {
|
||||
c.type_implements(right_type, expr_type, 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`',
|
||||
pos)
|
||||
}
|
||||
if (branch.cond.left is ast.Ident || branch.cond.left is ast.SelectorExpr)
|
||||
&& branch.cond.right is ast.TypeNode {
|
||||
is_variable := if mut branch.cond.left is ast.Ident {
|
||||
branch.cond.left.kind == .variable
|
||||
} else {
|
||||
true
|
||||
}
|
||||
if is_variable {
|
||||
if left_sym.kind in [.interface_, .sum_type] {
|
||||
c.smartcast(branch.cond.left, branch.cond.left_type,
|
||||
right_type, mut branch.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c.smartcast_if_conds(branch.cond, mut branch.scope)
|
||||
c.stmts(branch.stmts)
|
||||
}
|
||||
if expr_required {
|
||||
|
|
|
@ -5,10 +5,10 @@ vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte
|
|||
| ~~
|
||||
15 | println('not cool')
|
||||
16 | }
|
||||
vlib/v/checker/tests/is_type_invalid.vv:18:5: error: `Cat` doesn't implement method `speak` of interface `Animal`
|
||||
vlib/v/checker/tests/is_type_invalid.vv:18:7: error: `Cat` doesn't implement method `speak` of interface `Animal`
|
||||
16 | }
|
||||
17 | a := Animal(Dog{})
|
||||
18 | if a is Cat {
|
||||
| ~~~~~~~~
|
||||
| ~~
|
||||
19 | println('not cool either')
|
||||
20 | }
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
vlib/v/checker/tests/sum.vv:5:8: error: cannot cast non-sum type `int` using `as`
|
||||
3 | fn non_sum() {
|
||||
4 | v := 4
|
||||
5 | _ = v as rune
|
||||
| ~~
|
||||
6 | _ = v as Var
|
||||
7 | }
|
||||
vlib/v/checker/tests/sum.vv:6:8: error: cannot cast non-sum type `int` using `as` - use e.g. `Var(some_expr)` instead.
|
||||
4 | v := 4
|
||||
5 | _ = v as rune
|
||||
6 | _ = v as Var
|
||||
| ~~
|
||||
7 | }
|
||||
8 |
|
||||
vlib/v/checker/tests/sum.vv:10:7: error: cannot cast `rune` to `Var`
|
||||
8 |
|
||||
9 | fn sum() {
|
||||
10 | _ := Var(`J`)
|
||||
| ~~~~~~~~
|
||||
11 | mut s2 := Var('')
|
||||
12 | s2 = true
|
||||
vlib/v/checker/tests/sum.vv:12:7: error: cannot assign to `s2`: expected `Var`, not `bool`
|
||||
10 | _ := Var(`J`)
|
||||
11 | mut s2 := Var('')
|
||||
12 | s2 = true
|
||||
| ~~~~
|
||||
13 | _ = s2
|
||||
14 | }
|
|
@ -1,14 +0,0 @@
|
|||
type Var = int | string
|
||||
|
||||
fn non_sum() {
|
||||
v := 4
|
||||
_ = v as rune
|
||||
_ = v as Var
|
||||
}
|
||||
|
||||
fn sum() {
|
||||
_ := Var(`J`)
|
||||
mut s2 := Var('')
|
||||
s2 = true
|
||||
_ = s2
|
||||
}
|
|
@ -301,8 +301,8 @@ fn (f Fmt) should_insert_newline_before_node(node ast.Node, prev_node ast.Node)
|
|||
prev_line_nr := prev_node.position().last_line
|
||||
// The nodes are Stmts
|
||||
if node is ast.Stmt && prev_node is ast.Stmt {
|
||||
stmt := node as ast.Stmt
|
||||
prev_stmt := prev_node as ast.Stmt
|
||||
stmt := node
|
||||
prev_stmt := prev_node
|
||||
// Force a newline after a block of HashStmts
|
||||
if prev_stmt is ast.HashStmt && stmt !is ast.HashStmt && stmt !is ast.ExprStmt {
|
||||
return true
|
||||
|
@ -1662,8 +1662,7 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
|
|||
}
|
||||
for i, arg in args {
|
||||
if i == args.len - 1 && arg.expr is ast.StructInit {
|
||||
struct_expr := arg.expr as ast.StructInit
|
||||
if struct_expr.typ == ast.void_type {
|
||||
if arg.expr.typ == ast.void_type {
|
||||
f.use_short_fn_args = true
|
||||
}
|
||||
}
|
||||
|
@ -2477,7 +2476,7 @@ pub fn (mut f Fmt) prefix_expr_cast_expr(node ast.Expr) {
|
|||
mut is_pe_amp_ce := false
|
||||
if node is ast.PrefixExpr {
|
||||
if node.right is ast.CastExpr && node.op == .amp {
|
||||
mut ce := node.right as ast.CastExpr
|
||||
mut ce := node.right
|
||||
ce.typname = f.table.get_type_symbol(ce.typ).name
|
||||
is_pe_amp_ce = true
|
||||
f.expr(ce)
|
||||
|
|
|
@ -6422,6 +6422,8 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
|||
variant_sym := g.table.get_type_symbol(variant)
|
||||
g.as_cast_type_names[idx] = variant_sym.name
|
||||
}
|
||||
} else {
|
||||
g.expr(node.expr)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
struct Empty {}
|
||||
|
||||
struct SourcePosition {
|
||||
source_line u32
|
||||
source_column u32
|
||||
}
|
||||
|
||||
type SourcePositionType = Empty | SourcePosition
|
||||
type NameIndexType = Empty | u32
|
||||
|
||||
struct GenPosition {
|
||||
gen_line u32
|
||||
gen_column u32
|
||||
}
|
||||
|
||||
struct Mapping {
|
||||
GenPosition
|
||||
sources_ind u32
|
||||
names_ind NameIndexType
|
||||
source_position SourcePositionType
|
||||
}
|
||||
|
||||
fn ok(mapping_a Mapping, mapping_b Mapping) bool {
|
||||
if mapping_a.source_position is SourcePosition && mapping_b.source_position is SourcePosition {
|
||||
return mapping_a.source_position.source_line != mapping_b.source_position.source_line
|
||||
|| mapping_a.source_position.source_column != mapping_b.source_position.source_column
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fn test_if_smartcast_multi_conds() {
|
||||
a := Mapping{
|
||||
source_position: SourcePosition{
|
||||
source_line: 11
|
||||
source_column: 22
|
||||
}
|
||||
}
|
||||
b := Mapping{
|
||||
source_position: SourcePosition{
|
||||
source_line: 22
|
||||
source_column: 11
|
||||
}
|
||||
}
|
||||
ret := ok(a, b)
|
||||
println(ret)
|
||||
assert ret
|
||||
}
|
Loading…
Reference in New Issue