mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: fix for..in statement with ComptimeSelector (#16997)
This commit is contained in:
parent
f57b16a843
commit
1302dbf02f
@ -31,11 +31,19 @@ fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
|
||||
c.in_for_count--
|
||||
}
|
||||
|
||||
fn (mut c Checker) get_compselector_type_from_selector_name(node ast.ComptimeSelector) (bool, ast.Type) {
|
||||
if c.inside_comptime_for_field && node.field_expr is ast.SelectorExpr
|
||||
&& (node.field_expr as ast.SelectorExpr).expr.str() in c.comptime_fields_type
|
||||
&& (node.field_expr as ast.SelectorExpr).field_name == 'name' {
|
||||
return true, c.unwrap_generic(c.comptime_fields_default_type)
|
||||
}
|
||||
return false, ast.void_type
|
||||
}
|
||||
|
||||
fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
c.in_for_count++
|
||||
prev_loop_label := c.loop_label
|
||||
typ := c.expr(node.cond)
|
||||
typ_idx := typ.idx()
|
||||
mut typ := c.expr(node.cond)
|
||||
if node.key_var.len > 0 && node.key_var != '_' {
|
||||
c.check_valid_snake_case(node.key_var, 'variable name', node.pos)
|
||||
if reserved_type_names_chk.matches(node.key_var) {
|
||||
@ -49,6 +57,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
}
|
||||
}
|
||||
if node.is_range {
|
||||
typ_idx := typ.idx()
|
||||
high_type := c.expr(node.high)
|
||||
high_type_idx := high_type.idx()
|
||||
if typ_idx in ast.integer_type_idxs && high_type_idx !in ast.integer_type_idxs
|
||||
@ -75,12 +84,19 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
node.high_type = high_type
|
||||
node.scope.update_var_type(node.val_var, node.val_type)
|
||||
} else {
|
||||
sym := c.table.final_sym(typ)
|
||||
mut sym := c.table.final_sym(typ)
|
||||
if sym.kind != .string {
|
||||
match mut node.cond {
|
||||
ast.PrefixExpr {
|
||||
node.val_is_ref = node.cond.op == .amp
|
||||
}
|
||||
ast.ComptimeSelector {
|
||||
found, selector_type := c.get_compselector_type_from_selector_name(node.cond)
|
||||
if found {
|
||||
sym = c.table.final_sym(selector_type)
|
||||
typ = selector_type
|
||||
}
|
||||
}
|
||||
ast.Ident {
|
||||
match mut node.cond.info {
|
||||
ast.IdentVar {
|
||||
|
23
vlib/v/tests/for_comptime_selector_test.v
Normal file
23
vlib/v/tests/for_comptime_selector_test.v
Normal file
@ -0,0 +1,23 @@
|
||||
struct Test {
|
||||
b ?[]int
|
||||
}
|
||||
|
||||
fn call_generic[U](val U) int {
|
||||
mut out := 0
|
||||
$for field in U.fields {
|
||||
variable := val.$(field.name)
|
||||
println(variable)
|
||||
for element in val.$(field.name) {
|
||||
dump(element)
|
||||
out += element
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
test := Test{
|
||||
b: [1, 2, 3]
|
||||
}
|
||||
assert call_generic(test) == 6
|
||||
}
|
Loading…
Reference in New Issue
Block a user