mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: implement if smartcast multi conds (part 2) (#10487)
This commit is contained in:
parent
46eb6befd5
commit
c58b04bcbf
@ -2922,8 +2922,7 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
||||
if field_name.len > 0 && field_name[0].is_capital() && sym.info is ast.Struct
|
||||
&& sym.language == .v {
|
||||
// x.Foo.y => access the embedded struct
|
||||
sym_info := sym.info as ast.Struct
|
||||
for embed in sym_info.embeds {
|
||||
for embed in sym.info.embeds {
|
||||
embed_sym := c.table.get_type_symbol(embed)
|
||||
if embed_sym.embed_name() == field_name {
|
||||
node.typ = embed
|
||||
@ -4271,7 +4270,6 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||
if infix.op == .key_is {
|
||||
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
|
||||
&& infix.right is ast.TypeNode {
|
||||
right_expr := infix.right as ast.TypeNode
|
||||
is_variable := if mut infix.left is ast.Ident {
|
||||
infix.left.kind == .variable
|
||||
} else {
|
||||
@ -4281,7 +4279,8 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||
left_sym := c.table.get_type_symbol(left_type)
|
||||
if is_variable {
|
||||
if left_sym.kind in [.sum_type, .interface_] {
|
||||
c.smartcast(infix.left, infix.left_type, right_expr.typ, mut node.scope)
|
||||
c.smartcast(infix.left, infix.left_type, infix.right.typ, mut
|
||||
node.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4667,12 +4666,12 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
||||
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)
|
||||
}
|
||||
} 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)
|
||||
} else if node.expr_type != node.typ {
|
||||
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)
|
||||
}
|
||||
return node.typ
|
||||
}
|
||||
@ -5998,7 +5997,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
||||
} else if branch.cond.right is ast.TypeNode && left is ast.TypeNode
|
||||
&& sym.kind == .interface_ {
|
||||
// is interface
|
||||
checked_type := c.unwrap_generic((left as ast.TypeNode).typ)
|
||||
checked_type := c.unwrap_generic(left.typ)
|
||||
should_skip = !c.table.type_implements_interface(checked_type,
|
||||
got_type)
|
||||
} else if left is ast.TypeNode {
|
||||
@ -6187,8 +6186,7 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||
.key_is, .not_is {
|
||||
if cond.left is ast.TypeNode && cond.right is ast.TypeNode {
|
||||
// `$if Foo is Interface {`
|
||||
type_node := cond.right as ast.TypeNode
|
||||
sym := c.table.get_type_symbol(type_node.typ)
|
||||
sym := c.table.get_type_symbol(cond.right.typ)
|
||||
if sym.kind != .interface_ {
|
||||
c.expr(cond.left)
|
||||
// c.error('`$sym.name` is not an interface', cond.right.position())
|
||||
|
28
vlib/v/checker/tests/sum.out
Normal file
28
vlib/v/checker/tests/sum.out
Normal file
@ -0,0 +1,28 @@
|
||||
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 | }
|
14
vlib/v/checker/tests/sum.vv
Normal file
14
vlib/v/checker/tests/sum.vv
Normal file
@ -0,0 +1,14 @@
|
||||
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
|
||||
}
|
@ -325,7 +325,7 @@ fn (mut g Gen) comp_if_cond(cond ast.Expr) bool {
|
||||
interface_sym := g.table.get_type_symbol(got_type)
|
||||
if interface_sym.info is ast.Interface {
|
||||
// q := g.table.get_type_symbol(interface_sym.info.types[0])
|
||||
checked_type := g.unwrap_generic((left as ast.TypeNode).typ)
|
||||
checked_type := g.unwrap_generic(left.typ)
|
||||
// TODO PERF this check is run twice (also in the checker)
|
||||
// store the result in a field
|
||||
is_true := g.table.type_implements_interface(checked_type,
|
||||
|
@ -850,8 +850,7 @@ fn (mut g JsGen) gen_enum_decl(it ast.EnumDecl) {
|
||||
for field in it.fields {
|
||||
g.write('$field.name: ')
|
||||
if field.has_expr && field.expr is ast.IntegerLiteral {
|
||||
e := field.expr as ast.IntegerLiteral
|
||||
i = e.val.int()
|
||||
i = field.expr.val.int()
|
||||
}
|
||||
g.writeln('$i,')
|
||||
i++
|
||||
|
@ -150,8 +150,8 @@ fn compare_by_generated_positions_inflated(mapping_a Mapping, mapping_b Mapping)
|
||||
|
||||
if mapping_a.source_position.type_name() == mapping_b.source_position.type_name()
|
||||
&& mapping_b.source_position is SourcePosition {
|
||||
if
|
||||
(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 {
|
||||
if 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 true
|
||||
}
|
||||
} else {
|
||||
@ -161,8 +161,8 @@ fn compare_by_generated_positions_inflated(mapping_a Mapping, mapping_b Mapping)
|
||||
}
|
||||
|
||||
if mapping_a.names_ind.type_name() == mapping_b.names_ind.type_name()
|
||||
&& mapping_a.names_ind is IndexNumber {
|
||||
return (mapping_a.names_ind as IndexNumber) != (mapping_b.names_ind as IndexNumber)
|
||||
&& mapping_a.names_ind is IndexNumber && mapping_b.names_ind is IndexNumber {
|
||||
return mapping_a.names_ind != mapping_b.names_ind
|
||||
} else {
|
||||
return mapping_a.names_ind.type_name() != mapping_b.names_ind.type_name()
|
||||
}
|
||||
|
@ -34,8 +34,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||
if !is_count && where_expr is ast.InfixExpr {
|
||||
e := where_expr as ast.InfixExpr
|
||||
if e.op == .eq && e.left is ast.Ident {
|
||||
ident := e.left as ast.Ident
|
||||
if ident.name == 'id' {
|
||||
if e.left.name == 'id' {
|
||||
query_one = true
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user