Skip to content

Commit c58b04b

Browse files
authored
checker: implement if smartcast multi conds (part 2) (#10487)
1 parent 46eb6be commit c58b04b

File tree

7 files changed

+60
-22
lines changed

7 files changed

+60
-22
lines changed

vlib/v/checker/checker.v

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,8 +2922,7 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
29222922
if field_name.len > 0 && field_name[0].is_capital() && sym.info is ast.Struct
29232923
&& sym.language == .v {
29242924
// x.Foo.y => access the embedded struct
2925-
sym_info := sym.info as ast.Struct
2926-
for embed in sym_info.embeds {
2925+
for embed in sym.info.embeds {
29272926
embed_sym := c.table.get_type_symbol(embed)
29282927
if embed_sym.embed_name() == field_name {
29292928
node.typ = embed
@@ -4271,7 +4270,6 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
42714270
if infix.op == .key_is {
42724271
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
42734272
&& infix.right is ast.TypeNode {
4274-
right_expr := infix.right as ast.TypeNode
42754273
is_variable := if mut infix.left is ast.Ident {
42764274
infix.left.kind == .variable
42774275
} else {
@@ -4281,7 +4279,8 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
42814279
left_sym := c.table.get_type_symbol(left_type)
42824280
if is_variable {
42834281
if left_sym.kind in [.sum_type, .interface_] {
4284-
c.smartcast(infix.left, infix.left_type, right_expr.typ, mut node.scope)
4282+
c.smartcast(infix.left, infix.left_type, infix.right.typ, mut
4283+
node.scope)
42854284
}
42864285
}
42874286
}
@@ -4667,12 +4666,12 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
46674666
if !c.table.sumtype_has_variant(node.expr_type, node.typ) {
46684667
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
46694668
}
4670-
} else {
4671-
// mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
4672-
// if type_sym.kind == .sum_type {
4673-
// s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
4674-
// }
4675-
// c.error(s, node.pos)
4669+
} else if node.expr_type != node.typ {
4670+
mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
4671+
if type_sym.kind == .sum_type {
4672+
s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
4673+
}
4674+
c.error(s, node.pos)
46764675
}
46774676
return node.typ
46784677
}
@@ -5998,7 +5997,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
59985997
} else if branch.cond.right is ast.TypeNode && left is ast.TypeNode
59995998
&& sym.kind == .interface_ {
60005999
// is interface
6001-
checked_type := c.unwrap_generic((left as ast.TypeNode).typ)
6000+
checked_type := c.unwrap_generic(left.typ)
60026001
should_skip = !c.table.type_implements_interface(checked_type,
60036002
got_type)
60046003
} else if left is ast.TypeNode {
@@ -6187,8 +6186,7 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
61876186
.key_is, .not_is {
61886187
if cond.left is ast.TypeNode && cond.right is ast.TypeNode {
61896188
// `$if Foo is Interface {`
6190-
type_node := cond.right as ast.TypeNode
6191-
sym := c.table.get_type_symbol(type_node.typ)
6189+
sym := c.table.get_type_symbol(cond.right.typ)
61926190
if sym.kind != .interface_ {
61936191
c.expr(cond.left)
61946192
// c.error('`$sym.name` is not an interface', cond.right.position())

vlib/v/checker/tests/sum.out

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
vlib/v/checker/tests/sum.vv:5:8: error: cannot cast non-sum type `int` using `as`
2+
3 | fn non_sum() {
3+
4 | v := 4
4+
5 | _ = v as rune
5+
| ~~
6+
6 | _ = v as Var
7+
7 | }
8+
vlib/v/checker/tests/sum.vv:6:8: error: cannot cast non-sum type `int` using `as` - use e.g. `Var(some_expr)` instead.
9+
4 | v := 4
10+
5 | _ = v as rune
11+
6 | _ = v as Var
12+
| ~~
13+
7 | }
14+
8 |
15+
vlib/v/checker/tests/sum.vv:10:7: error: cannot cast `rune` to `Var`
16+
8 |
17+
9 | fn sum() {
18+
10 | _ := Var(`J`)
19+
| ~~~~~~~~
20+
11 | mut s2 := Var('')
21+
12 | s2 = true
22+
vlib/v/checker/tests/sum.vv:12:7: error: cannot assign to `s2`: expected `Var`, not `bool`
23+
10 | _ := Var(`J`)
24+
11 | mut s2 := Var('')
25+
12 | s2 = true
26+
| ~~~~
27+
13 | _ = s2
28+
14 | }

vlib/v/checker/tests/sum.vv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
type Var = int | string
2+
3+
fn non_sum() {
4+
v := 4
5+
_ = v as rune
6+
_ = v as Var
7+
}
8+
9+
fn sum() {
10+
_ := Var(`J`)
11+
mut s2 := Var('')
12+
s2 = true
13+
_ = s2
14+
}

vlib/v/gen/c/comptime.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ fn (mut g Gen) comp_if_cond(cond ast.Expr) bool {
325325
interface_sym := g.table.get_type_symbol(got_type)
326326
if interface_sym.info is ast.Interface {
327327
// q := g.table.get_type_symbol(interface_sym.info.types[0])
328-
checked_type := g.unwrap_generic((left as ast.TypeNode).typ)
328+
checked_type := g.unwrap_generic(left.typ)
329329
// TODO PERF this check is run twice (also in the checker)
330330
// store the result in a field
331331
is_true := g.table.type_implements_interface(checked_type,

vlib/v/gen/js/js.v

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,8 +850,7 @@ fn (mut g JsGen) gen_enum_decl(it ast.EnumDecl) {
850850
for field in it.fields {
851851
g.write('$field.name: ')
852852
if field.has_expr && field.expr is ast.IntegerLiteral {
853-
e := field.expr as ast.IntegerLiteral
854-
i = e.val.int()
853+
i = field.expr.val.int()
855854
}
856855
g.writeln('$i,')
857856
i++

vlib/v/gen/js/sourcemap/mappings.v

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ fn compare_by_generated_positions_inflated(mapping_a Mapping, mapping_b Mapping)
150150

151151
if mapping_a.source_position.type_name() == mapping_b.source_position.type_name()
152152
&& mapping_b.source_position is SourcePosition {
153-
if
154-
(mapping_a.source_position as SourcePosition).source_line != (mapping_b.source_position as SourcePosition).source_line || (mapping_a.source_position as SourcePosition).source_column != (mapping_b.source_position as SourcePosition).source_column {
153+
if mapping_a.source_position.source_line != mapping_b.source_position.source_line
154+
|| mapping_a.source_position.source_column != mapping_b.source_position.source_column {
155155
return true
156156
}
157157
} else {
@@ -161,8 +161,8 @@ fn compare_by_generated_positions_inflated(mapping_a Mapping, mapping_b Mapping)
161161
}
162162

163163
if mapping_a.names_ind.type_name() == mapping_b.names_ind.type_name()
164-
&& mapping_a.names_ind is IndexNumber {
165-
return (mapping_a.names_ind as IndexNumber) != (mapping_b.names_ind as IndexNumber)
164+
&& mapping_a.names_ind is IndexNumber && mapping_b.names_ind is IndexNumber {
165+
return mapping_a.names_ind != mapping_b.names_ind
166166
} else {
167167
return mapping_a.names_ind.type_name() != mapping_b.names_ind.type_name()
168168
}

vlib/v/parser/sql.v

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
3434
if !is_count && where_expr is ast.InfixExpr {
3535
e := where_expr as ast.InfixExpr
3636
if e.op == .eq && e.left is ast.Ident {
37-
ident := e.left as ast.Ident
38-
if ident.name == 'id' {
37+
if e.left.name == 'id' {
3938
query_one = true
4039
}
4140
}

0 commit comments

Comments
 (0)