diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index 92606b79a7..ab44285fd7 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -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', diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 87d7aed186..8bd3677150 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -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 } diff --git a/vlib/v/tests/comptime_arr_type_test.v b/vlib/v/tests/comptime_arr_type_test.v new file mode 100644 index 0000000000..6a39aac709 --- /dev/null +++ b/vlib/v/tests/comptime_arr_type_test.v @@ -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' +} diff --git a/vlib/v/tests/comptime_selector_member_test.v b/vlib/v/tests/comptime_selector_member_test.v new file mode 100644 index 0000000000..b50959fdda --- /dev/null +++ b/vlib/v/tests/comptime_selector_member_test.v @@ -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' +} diff --git a/vlib/v/tests/for_smartcast_test.v b/vlib/v/tests/for_smartcast_test.v index ea327cb925..393a0652d7 100644 --- a/vlib/v/tests/for_smartcast_test.v +++ b/vlib/v/tests/for_smartcast_test.v @@ -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 } }