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:
parent
838d0e8960
commit
578264c815
@ -742,11 +742,9 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran
|
||||
}
|
||||
}
|
||||
.key_in, .not_in {
|
||||
if cond.left is ast.Ident {
|
||||
c.expr(cond.left)
|
||||
}
|
||||
if cond.left in [ast.TypeNode, ast.SelectorExpr, ast.Ident]
|
||||
&& cond.right is ast.ArrayInit {
|
||||
c.expr(cond.left)
|
||||
for expr in cond.right.exprs {
|
||||
if expr !in [ast.ComptimeType, ast.TypeNode] {
|
||||
c.error('invalid `\$if` condition, only types are allowed',
|
||||
|
@ -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 {
|
||||
if (node is ast.Ident && g.is_comptime_var(node)) || node is ast.ComptimeSelector {
|
||||
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
|
||||
}
|
||||
|
24
vlib/v/tests/comptime_arr_type_test.v
Normal file
24
vlib/v/tests/comptime_arr_type_test.v
Normal 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'
|
||||
}
|
36
vlib/v/tests/comptime_selector_member_test.v
Normal file
36
vlib/v/tests/comptime_selector_member_test.v
Normal 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'
|
||||
}
|
@ -16,7 +16,7 @@ fn test_nested_sumtype_selector() {
|
||||
pos: 1
|
||||
}))}
|
||||
for c.node is Expr {
|
||||
assert typeof(c.node).name == 'Expr'
|
||||
assert typeof(c.node).name == 'Node'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user