checker: implement if smartcast multi conds (part 2) (#10487)
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
|
if field_name.len > 0 && field_name[0].is_capital() && sym.info is ast.Struct
|
||||||
&& sym.language == .v {
|
&& sym.language == .v {
|
||||||
// x.Foo.y => access the embedded struct
|
// 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)
|
embed_sym := c.table.get_type_symbol(embed)
|
||||||
if embed_sym.embed_name() == field_name {
|
if embed_sym.embed_name() == field_name {
|
||||||
node.typ = embed
|
node.typ = embed
|
||||||
|
@ -4271,7 +4270,6 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||||
if infix.op == .key_is {
|
if infix.op == .key_is {
|
||||||
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
|
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
|
||||||
&& infix.right is ast.TypeNode {
|
&& infix.right is ast.TypeNode {
|
||||||
right_expr := infix.right as ast.TypeNode
|
|
||||||
is_variable := if mut infix.left is ast.Ident {
|
is_variable := if mut infix.left is ast.Ident {
|
||||||
infix.left.kind == .variable
|
infix.left.kind == .variable
|
||||||
} else {
|
} else {
|
||||||
|
@ -4281,7 +4279,8 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||||
left_sym := c.table.get_type_symbol(left_type)
|
left_sym := c.table.get_type_symbol(left_type)
|
||||||
if is_variable {
|
if is_variable {
|
||||||
if left_sym.kind in [.sum_type, .interface_] {
|
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) {
|
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('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else if node.expr_type != node.typ {
|
||||||
// mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
|
mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`'
|
||||||
// if type_sym.kind == .sum_type {
|
if type_sym.kind == .sum_type {
|
||||||
// s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
|
s += ' - use e.g. `${type_sym.name}(some_expr)` instead.'
|
||||||
// }
|
}
|
||||||
// c.error(s, node.pos)
|
c.error(s, node.pos)
|
||||||
}
|
}
|
||||||
return node.typ
|
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
|
} else if branch.cond.right is ast.TypeNode && left is ast.TypeNode
|
||||||
&& sym.kind == .interface_ {
|
&& sym.kind == .interface_ {
|
||||||
// is 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,
|
should_skip = !c.table.type_implements_interface(checked_type,
|
||||||
got_type)
|
got_type)
|
||||||
} else if left is ast.TypeNode {
|
} 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 {
|
.key_is, .not_is {
|
||||||
if cond.left is ast.TypeNode && cond.right is ast.TypeNode {
|
if cond.left is ast.TypeNode && cond.right is ast.TypeNode {
|
||||||
// `$if Foo is Interface {`
|
// `$if Foo is Interface {`
|
||||||
type_node := cond.right as ast.TypeNode
|
sym := c.table.get_type_symbol(cond.right.typ)
|
||||||
sym := c.table.get_type_symbol(type_node.typ)
|
|
||||||
if sym.kind != .interface_ {
|
if sym.kind != .interface_ {
|
||||||
c.expr(cond.left)
|
c.expr(cond.left)
|
||||||
// c.error('`$sym.name` is not an interface', cond.right.position())
|
// c.error('`$sym.name` is not an interface', cond.right.position())
|
||||||
|
|
|
@ -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 | }
|
|
@ -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)
|
interface_sym := g.table.get_type_symbol(got_type)
|
||||||
if interface_sym.info is ast.Interface {
|
if interface_sym.info is ast.Interface {
|
||||||
// q := g.table.get_type_symbol(interface_sym.info.types[0])
|
// 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)
|
// TODO PERF this check is run twice (also in the checker)
|
||||||
// store the result in a field
|
// store the result in a field
|
||||||
is_true := g.table.type_implements_interface(checked_type,
|
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 {
|
for field in it.fields {
|
||||||
g.write('$field.name: ')
|
g.write('$field.name: ')
|
||||||
if field.has_expr && field.expr is ast.IntegerLiteral {
|
if field.has_expr && field.expr is ast.IntegerLiteral {
|
||||||
e := field.expr as ast.IntegerLiteral
|
i = field.expr.val.int()
|
||||||
i = e.val.int()
|
|
||||||
}
|
}
|
||||||
g.writeln('$i,')
|
g.writeln('$i,')
|
||||||
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()
|
if mapping_a.source_position.type_name() == mapping_b.source_position.type_name()
|
||||||
&& mapping_b.source_position is SourcePosition {
|
&& mapping_b.source_position is SourcePosition {
|
||||||
if
|
if mapping_a.source_position.source_line != mapping_b.source_position.source_line
|
||||||
(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 {
|
|| mapping_a.source_position.source_column != mapping_b.source_position.source_column {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
} 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()
|
if mapping_a.names_ind.type_name() == mapping_b.names_ind.type_name()
|
||||||
&& mapping_a.names_ind is IndexNumber {
|
&& mapping_a.names_ind is IndexNumber && mapping_b.names_ind is IndexNumber {
|
||||||
return (mapping_a.names_ind as IndexNumber) != (mapping_b.names_ind as IndexNumber)
|
return mapping_a.names_ind != mapping_b.names_ind
|
||||||
} else {
|
} else {
|
||||||
return mapping_a.names_ind.type_name() != mapping_b.names_ind.type_name()
|
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 {
|
if !is_count && where_expr is ast.InfixExpr {
|
||||||
e := where_expr as ast.InfixExpr
|
e := where_expr as ast.InfixExpr
|
||||||
if e.op == .eq && e.left is ast.Ident {
|
if e.op == .eq && e.left is ast.Ident {
|
||||||
ident := e.left as ast.Ident
|
if e.left.name == 'id' {
|
||||||
if ident.name == 'id' {
|
|
||||||
query_one = true
|
query_one = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue