1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix comptime selector evaluate when checked against type of array (#18774)

This commit is contained in:
Felipe Pena 2023-07-04 16:42:55 -03:00 committed by GitHub
parent 838d0e8960
commit 578264c815
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 4 deletions

View File

@ -742,11 +742,9 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran
} }
} }
.key_in, .not_in { .key_in, .not_in {
if cond.left is ast.Ident {
c.expr(cond.left)
}
if cond.left in [ast.TypeNode, ast.SelectorExpr, ast.Ident] if cond.left in [ast.TypeNode, ast.SelectorExpr, ast.Ident]
&& cond.right is ast.ArrayInit { && cond.right is ast.ArrayInit {
c.expr(cond.left)
for expr in cond.right.exprs { for expr in cond.right.exprs {
if expr !in [ast.ComptimeType, ast.TypeNode] { if expr !in [ast.ComptimeType, ast.TypeNode] {
c.error('invalid `\$if` condition, only types are allowed', c.error('invalid `\$if` condition, only types are allowed',

View File

@ -796,6 +796,11 @@ fn (mut g Gen) get_comptime_var_type(node ast.Expr) ast.Type {
fn (mut g Gen) resolve_comptime_type(node ast.Expr, default_type ast.Type) ast.Type { fn (mut g Gen) resolve_comptime_type(node ast.Expr, default_type ast.Type) ast.Type {
if (node is ast.Ident && g.is_comptime_var(node)) || node is ast.ComptimeSelector { if (node is ast.Ident && g.is_comptime_var(node)) || node is ast.ComptimeSelector {
return g.get_comptime_var_type(node) return g.get_comptime_var_type(node)
} else if node is ast.SelectorExpr {
sym := g.table.sym(g.unwrap_generic(node.expr_type))
if f := g.table.find_field_with_embeds(sym, node.field_name) {
return f.typ
}
} }
return default_type return default_type
} }

View File

@ -0,0 +1,24 @@
struct TestStruct {
test string
}
fn test[T](val T) string {
$if T is $struct {
$for attribute in T.fields {
$if attribute.name == 'test' {
$if val.test in [u32, i32, $int] {
return 'struct field ${typeof(val.test).name}'
} $else {
return 'got type: ${typeof(val.test).name}'
}
}
}
return 'no test field in struct'
} $else {
return 'empty'
}
}
fn test_main() {
assert test(TestStruct{'7'}) == 'got type: string'
}

View File

@ -0,0 +1,36 @@
struct OtherStruct {
test string
}
struct I32Struct {
test i32
}
struct U32Struct {
test u32
}
fn test[T](val T) string {
$if val is $struct {
println(T.name)
$for attribute in T.fields {
$if attribute.name == 'test' {
$if val.test in [u32, i32] {
return 'struct field ${typeof(val.test).name}'
} $else {
return 'not u32 or i32 struct field, got type: ${typeof(val.test).name}'
}
}
}
return 'no test field in struct'
} $else {
return 'else block'
}
}
fn test_main() {
assert test(u32(7)) == 'else block'
assert test(OtherStruct{'7'}) == 'struct field string'
assert test(I32Struct{-7}) == 'struct field i32'
assert test(U32Struct{7}) == 'struct field u32'
}

View File

@ -16,7 +16,7 @@ fn test_nested_sumtype_selector() {
pos: 1 pos: 1
}))} }))}
for c.node is Expr { for c.node is Expr {
assert typeof(c.node).name == 'Expr' assert typeof(c.node).name == 'Node'
break break
} }
} }