checker: implement if smartcast multi conds (part 2) (#10487)

pull/10493/head
yuyi 2021-06-17 17:27:31 +08:00 committed by GitHub
parent 46eb6befd5
commit c58b04bcbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 22 deletions

View File

@ -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())

View 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 | }

View 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
}

View File

@ -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,

View File

@ -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++

View File

@ -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()
}

View File

@ -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
}
}